react-beautiful-dnd#DragDropContext JavaScript Examples

The following examples show how to use react-beautiful-dnd#DragDropContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js    From react-material-ui-table-row-drag-and-drop with Creative Commons Zero v1.0 Universal 6 votes vote down vote up
DroppableComponent = (
    onDragEnd: (result, provided) => void) => (props) =>
{
    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId={'1'} direction="vertical">
                {(provided) => {
                    return (
                        <TableBody ref={provided.innerRef} {...provided.droppableProps} {...props}>
                            {props.children}
                            {provided.placeholder}
                        </TableBody>
                    )
                }}
            </Droppable>
        </DragDropContext>
    )
}
Example #2
Source File: SortableList.jsx    From notence with MIT License 6 votes vote down vote up
export default function SortableList({ items, onSort, children }) {
  const handleDragEnd = (result) => {
    if (!result.destination) {
      return;
    }

    const [startIndex, endIndex] = [result.source.index, result.destination.index];
    onSort({ startIndex, endIndex });
  };

  const renderListItem = (item) => (draggableProvided) => {
    const restProps = {
      innerRef: draggableProvided.innerRef,
      ...draggableProvided.draggableProps,
      ...draggableProvided.dragHandleProps,
    };

    return children(item, restProps);
  };

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <Droppable droppableId="sortableList">
        {(provided) => (
          // eslint-disable-next-line react/jsx-props-no-spreading
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {items.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {renderListItem(item)}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}
Example #3
Source File: index.js    From rainbow-modules with MIT License 6 votes vote down vote up
DraggableList = (props) => {
    const { className, style, onDragEnd, data, keyField, ...rest } = props;

    const handleDragEnd = (result) => {
        if (!result.destination) {
            return;
        }
        if (result.destination.index === result.source.index) {
            return;
        }
        const newData = reorder(data, result.source.index, result.destination.index);
        onDragEnd(newData);
    };

    if (keyField && typeof keyField === 'string') {
        return (
            <DragDropContext onDragEnd={handleDragEnd}>
                <Droppable droppableId="draggable-list-droppable-container">
                    {(provided) => {
                        return (
                            <Container
                                className={className}
                                style={style}
                                ref={provided.innerRef}
                                {...provided.droppableProps}
                            >
                                <Items data={data} keyField={keyField} {...rest} />
                                {provided.placeholder}
                            </Container>
                        );
                    }}
                </Droppable>
            </DragDropContext>
        );
    }
    // eslint-disable-next-line no-console
    console.error('The "keyField" is a required prop of the DraggableList component.');
    return null;
}
Example #4
Source File: Board.js    From TrelloClone with MIT License 5 votes vote down vote up
Board = ({ match }) => {
  const board = useSelector((state) => state.board.board);
  const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(getBoard(match.params.id));
  }, [dispatch, match.params.id]);

  useEffect(() => {
    if (board?.title) document.title = board.title + ' | TrelloClone';
  }, [board?.title]);

  if (!isAuthenticated) {
    return <Redirect to='/' />;
  }

  const onDragEnd = (result) => {
    const { source, destination, draggableId, type } = result;
    if (!destination) {
      return;
    }
    if (type === 'card') {
      dispatch(
        moveCard(draggableId, {
          fromId: source.droppableId,
          toId: destination.droppableId,
          toIndex: destination.index,
        })
      );
    } else {
      dispatch(moveList(draggableId, { toIndex: destination.index }));
    }
  };

  return !board ? (
    <Fragment>
      <Navbar />
      <Box className='board-loading'>
        <CircularProgress />
      </Box>
    </Fragment>
  ) : (
    <div
      className='board-and-navbar'
      style={{
        backgroundImage:
          'url(' +
          (board.backgroundURL
            ? board.backgroundURL
            : 'https://images.unsplash.com/photo-1598197748967-b4674cb3c266?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2689&q=80') +
          ')',
      }}
    >
      <Navbar />
      <section className='board'>
        <div className='board-top'>
          <div className='board-top-left'>
            <BoardTitle board={board} />
            <Members />
          </div>
          <BoardDrawer />
        </div>
        <DragDropContext onDragEnd={onDragEnd}>
          <Droppable droppableId='all-lists' direction='horizontal' type='list'>
            {(provided) => (
              <div className='lists' ref={provided.innerRef} {...provided.droppableProps}>
                {board.lists.map((listId, index) => (
                  <List key={listId} listId={listId} index={index} />
                ))}
                {provided.placeholder}
                <CreateList />
              </div>
            )}
          </Droppable>
        </DragDropContext>
      </section>
    </div>
  );
}
Example #5
Source File: KanbanBoard.jsx    From react_53 with MIT License 5 votes vote down vote up
function KanbanBoard(props) {
  const { loadTasks, data, changeTask, isLoading, toggleModal, isVisible } =
    props;
  useEffect(() => {
    if (!data.tasks) loadTasks();
  }, []);

  function handlerOnClick() {
    toggleModal();
  }

  function handlerDragEnd(result) {
    if (result.destination) {
      const checkDroppableId =
        result.destination.droppableId === result.source.droppableId;
      const checkIndex = result.destination.index === result.source.index;
      if (!(checkDroppableId && checkIndex)) changeTask(result);
    }
  }

  return (
    <div className={styles.mainBoardWrap}>
      <DragDropContext onDragEnd={handlerDragEnd}>
        <div className={styles.header}>
          <Button onClick={handlerOnClick} text="Add new task" />
        </div>
        <div className={styles.mainBoard}>
          {data.columnOrder.map((column) => {
            const { id, title, tasksId } = data.columns[column];
            const columnId = data.columns[column].id;
            return (
              <Board
                key={id}
                columnId={columnId}
                title={title}
                tasks={tasksId.map((task) => data.tasks[task])}
              />
            );
          })}
        </div>
        <Loader isLoading={isLoading} />
        <Modal isVisible={isVisible} toggleModal={toggleModal}>
          <NewTaskForm />
        </Modal>
      </DragDropContext>
    </div>
  );
}
Example #6
Source File: Kanban.js    From social-media-strategy-fe with MIT License 5 votes vote down vote up
Kanban = () => {
  const { lists } = useSelector(state => state.kanban);
  const user = useSelector(state => state.user);

  const { kanban, loading } = useStyles();
  const dispatch = useDispatch();

  useEffect(() => {
    if (user.okta_uid) {
      if (!lists) {
        (async () => {
          dispatch(await loadListsFromDb(user.okta_uid));
        })();
      }
    }
    // eslint-disable-next-line
  }, [user]);

  const onDragEnd = result => {
    const { source, destination, type } = result;

    if (
      !result.destination ||
      (source.droppableId === destination.droppableId &&
        source.index === destination.index)
    ) {
      return;
    }

    if (type === "post") {
      if (source.droppableId !== destination.droppableId) {
        // if drag post to a different list/column
        dispatch(dragPostToDifferentList(lists, source, destination));
      } else {
        // if drag post to the same list/column
        dispatch(dragPostToSameList(lists, source, destination));
      }
    } else if (type === "list") {
      // if drag list
      dispatch(dragList(lists, source, destination));
    }
  };

  return lists ? (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable direction="horizontal" droppableId="mainDroppable" type="list">
        {(provided, snapshot) => (
          <div
            {...provided.droppableProps}
            ref={provided.innerRef}
            className={kanban}
          >
            {Object.entries(lists)
              .sort((a, b) => a.index - b.index)
              .map(([listId, list]) => (
                <List key={list.id} list={list} user={user} />
              ))}
            {provided.placeholder}
            <CreateList />
          </div>
        )}
      </Droppable>
    </DragDropContext>
  ) : (
    <div className={loading}>
      <CircularProgress />
    </div>
  );
}
Example #7
Source File: SortableBoard.jsx    From notence with MIT License 5 votes vote down vote up
export default function SortableBoard({ groups, onChange, onItemCreate, children }) {
  const handleDragEnd = (result) => {
    if (!result.destination) {
      return;
    }

    onChange(result);
  };

  const renderItem = (item) => (draggableProvided) => {
    const restProps = {
      innerRef: draggableProvided.innerRef,
      ...draggableProvided.draggableProps,
      ...draggableProvided.dragHandleProps,
    };

    return children(item, restProps);
  };

  return (
    <DragDropContext onDragEnd={handleDragEnd}>
      <BoardWrapper>
        {Object.entries(groups).map(([groupId, group]) => (
          <Board key={groupId}>
            <BoardTitle>{group.name}</BoardTitle>

            <Droppable droppableId={groupId}>
              {(provided) => (
                // eslint-disable-next-line react/jsx-props-no-spreading
                <BoardContent {...provided.droppableProps} ref={provided.innerRef}>
                  {group.items.map((item, index) => (
                    <Draggable key={item.id} draggableId={item.id} index={index}>
                      {renderItem(item)}
                    </Draggable>
                  ))}
                  {provided.placeholder}

                  <AddBtn onClick={() => onItemCreate(groupId)} icon={<PlusOutlined />}>
                    New
                  </AddBtn>
                </BoardContent>
              )}
            </Droppable>
          </Board>
        ))}
      </BoardWrapper>
    </DragDropContext>
  );
}
Example #8
Source File: index.jsx    From react-antd-admin-template with MIT License 5 votes vote down vote up
render() {
    const path = this.props.location.pathname;
    const openKey = this.state.openKey;
    return (
      <div className="sidebar-menu-container">
        <Scrollbars autoHide autoHideTimeout={1000} autoHideDuration={200}>
          <DragDropContext onDragEnd={this.onDragEnd}>
            <Droppable droppableId="droppable">
              {(provided, snapshot) => (
                <div {...provided.droppableProps} ref={provided.innerRef}>
                  {this.state.menuTreeNode.map((item, index) => (
                    <Draggable
                      key={item.key}
                      draggableId={item.key}
                      index={index}
                    >
                      {(provided, snapshot) => (
                        <div
                          ref={provided.innerRef}
                          {...provided.draggableProps}
                          {...provided.dragHandleProps}
                        >
                          <Menu
                            mode="inline"
                            theme="dark"
                            onSelect={this.handleMenuSelect}
                            selectedKeys={[path]}
                            defaultOpenKeys={openKey}
                          >
                            {item}
                          </Menu>
                        </div>
                      )}
                    </Draggable>
                  ))}
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </Scrollbars>
      </div>
    );
  }
Example #9
Source File: DragDrop.js    From google-forms with MIT License 5 votes vote down vote up
export default function DragAndDrop(){
  // constructor(props) {
  //   super(props);
  //   this.state = {
  //     items: [ {id: "item-0", content: "item 0"},
  //     {id: "item-1", content: "item 1"}
  //     ,{id: "item-2", content: "item 2"}
  //     ,{id: "item-3", content: "item 3"}
  //     ,{id: "item-4", content: "item 4"}]
  //   };

  //   this.onDragEnd = this.onDragEnd.bind(this);
  // }

  const [items, setItems] = React.useState([ {id: "item-0", content: "item 0"},
  {id: "item-1", content: "item 1"}
  ,{id: "item-2", content: "item 2"}
  ,{id: "item-3", content: "item 3"}
  ,{id: "item-4", content: "item 4"}])


 function onDragEnd(result) {
    if (!result.destination) {
      return;
    }
    var itemgg = [...items]
    const itemF = reorder(
      itemgg,
      result.source.index,
      result.destination.index
    );
    setItems(itemF)
  }
  
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

    return (
      <DragDropContext onDragEnd={onDragEnd}>
        <Droppable droppableId="droppable">
          {(provided, snapshot) => (
            <div
              {...provided.droppableProps}
              ref={provided.innerRef}
            >
              {items.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index={index}>
                  {(provided, snapshot) => (
                    <div
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}

                    >
                      {item.content}
                    </div>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    );
}
Example #10
Source File: QuestionContainerLayout.js    From Edlib with GNU General Public License v3.0 5 votes vote down vote up
QuestionContainerLayout = props => {
    const {
        cards,
        onTitleChange,
        title,
        onQuestionBankSelect,
        tags,
        onTagsChange,
        cardsComponents,
        displayDialog,
        loadingIcon,
        loadingText,
        loadingTitle,
        editMode,
        handleDragEnd,
        searchTitle,
        placeholder,
    } = props;
    return (
        <div className="questionSetSurface">
            <div>
                <TextField
                    placeholder={placeholder}
                    label={<FormattedMessage id="QUESTIONCONTAINER.TITLE_LABEL" />}
                    fullWidth={true}
                    onChange={event => onTitleChange(event.currentTarget.value, true)}
                    value={title}
                    InputLabelProps={{
                        shrink: true,
                    }}
                    margin="normal"
                    inputProps={{
                        onBlur: event => onTitleChange(event.currentTarget.value, false),
                    }}
                />
                <TagsManager
                    tags={tags}
                    onChange={onTagsChange}
                />
                <DragDropContext onDragEnd={handleDragEnd}>
                    <Droppable
                        droppableId="questionSetDropZone"
                    >
                        {(provided, snapshot) => (
                            <div
                                ref={provided.innerRef}
                                {...provided.droppableProps}
                            >
                                {cardsComponents}
                                {provided.placeholder}
                            </div>
                        )}
                    </Droppable>
                </DragDropContext>
            </div>
            {typeof onQuestionBankSelect === 'function' && (
                <div>
                    <QuestionBankBrowser
                        onSelect={onQuestionBankSelect}
                        cards={cards}
                        title={searchTitle}
                        tags={tags}
                    />
                </div>
            )}
            <LoadingModal
                open={displayDialog}
                contentTitle={loadingTitle}
                contentIcon={loadingIcon}
                contentText={loadingText}
            />
        </div>
    );
}
Example #11
Source File: QuestionsTab.js    From google-forms with MIT License 4 votes vote down vote up
function QuestionsTab(props) {

  const [questions, setQuestions]= React.useState([]);
  const [openUploadImagePop, setOpenUploadImagePop] = React.useState(false);
  const [imageContextData, setImageContextData] = React.useState({question: null, option: null});
  const [formData, setFormData] = React.useState({});
  const [loadingFormData, setLoadingFormData] = React.useState(true);
  

  React.useEffect(()=>{
    
    if(props.formData.questions !== undefined){
      //console.log(props.formData.questions.length);
      if(props.formData.questions.length === 0){
        setQuestions([{questionText: "Question", options : [{optionText: "Option 1"}], open: false}]);
      } else{
        setQuestions(props.formData.questions)
      }
      setLoadingFormData(false)
    } 
    setFormData(props.formData)
  }, [props.formData])
  

  function saveQuestions(){
    console.log("auto saving questions initiated");
    var data = {
      formId: formData._id,
      name: formData.name,
      description: formData.description,
      questions: questions
    }

    formService.autoSave(data)
    .then((result) => {     
         console.log(result);
         setQuestions(result.questions)
        },
        error => {
        const resMessage =
            (error.response &&
            error.response.data &&
            error.response.data.message) ||
            error.message ||
            error.toString();
            console.log(resMessage);
        }
    );
    
  }

  function checkImageHereOrNotForQuestion(gg){
   // console.log(gg);
    if ((gg === undefined)||(gg==="")){
      return false;
    } else{
      return true;
    }
  }

  function checkImageHereOrNotForOption(gg){
   // console.log(gg);
    if ((gg === undefined)||(gg==="")){
      return false;
    } else{
      return true;
    }
  }

  function addMoreQuestionField(){
      expandCloseAll(); //I AM GOD

      setQuestions(questions=> [...questions, {questionText: "Question", options : [{optionText: "Option 1"}], open: true}]);
  }

  function copyQuestion(i){
    let qs = [...questions]; 
    expandCloseAll();
    const myNewOptions = [];
    qs[i].options.forEach(opn => {
      if ((opn.optionImage !== undefined)||(opn.optionImage !=="")) {
        var opn1new = {
          optionText : opn.optionText,
          optionImage: opn.optionImage
        }
      } else{
        var opn1new = {
          optionText : opn.optionText
        }
      }
      myNewOptions.push(opn1new)
    });
    const qImage = qs[i].questionImage || "";
    var newQuestion = {questionText: qs[i].questionText, questionImage : qImage ,options:myNewOptions, open: true}
     setQuestions(questions=> [...questions, newQuestion]); 
  }

  const handleImagePopupOpen = () => {
    setOpenUploadImagePop(true);
  };


  function uploadImage(i, j){
    
    setImageContextData({
      question: i,
      option: j
    });
    handleImagePopupOpen();
    
  }

  function updateImageLink(link, context){
    
    var optionsOfQuestion = [...questions];
    var i = context.question

    if (context.option == null) {
      optionsOfQuestion[i].questionImage= link;
    } else {
      var j = context.option
      optionsOfQuestion[i].options[j].optionImage = link;
    }
    setQuestions(optionsOfQuestion);
  }

  function deleteQuestion(i){
    let qs = [...questions]; 
    if(questions.length > 1){
      qs.splice(i, 1);
    }
    setQuestions(qs)
  }

  function handleOptionValue(text,i, j){
    var optionsOfQuestion = [...questions];
    optionsOfQuestion[i].options[j].optionText = text;
    //newMembersEmail[i]= email;
      setQuestions(optionsOfQuestion);
  }

  function handleQuestionValue(text, i){
    var optionsOfQuestion = [...questions];
    optionsOfQuestion[i].questionText = text;
      setQuestions(optionsOfQuestion);
  }

 function onDragEnd(result) {
  if (!result.destination) {
    return;
  }
  var itemgg = [...questions];

  const itemF = reorder(
    itemgg,
    result.source.index,
    result.destination.index
  );

  setQuestions(itemF);
  }

  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  function showAsQuestion(i){
    let qs = [...questions];  
     qs[i].open = false;
     setQuestions(qs);
  }

  function addOption(i){
    var optionsOfQuestion = [...questions];
    if(optionsOfQuestion[i].options.length < 5){
      optionsOfQuestion[i].options.push({optionText: "Option " + (optionsOfQuestion[i].options.length + 1)})
    } else{
      console.log("Max  5 options ");  
    }
    //console.log(optionsOfQuestion);
    setQuestions(optionsOfQuestion)
  }

  function removeOption(i, j){
    var optionsOfQuestion = [...questions];
    if(optionsOfQuestion[i].options.length > 1){
      optionsOfQuestion[i].options.splice(j, 1);
      setQuestions(optionsOfQuestion)
      console.log(i + "__" + j);
    }   
  }

  function expandCloseAll(){
    let qs = [...questions]; 
     for (let j = 0; j < qs.length; j++) {  
      qs[j].open = false;
     }
     setQuestions(qs);
  }

  function handleExpand(i){
    let qs = [...questions]; 
    for (let j = 0; j < qs.length; j++) {
      if(i ===j ){
        qs[i].open = true;
 
      } else{
        qs[j].open = false;
       }
    }
     setQuestions(qs);
  }

  function questionsUI(){
    return  questions.map((ques, i)=> (
      <Draggable key={i} draggableId={i + 'id'} index={i}>
                  {(provided, snapshot) => (
                    <div
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                    >
                      <div>
          <div style={{marginBottom: "15px"}}>
            <div style={{width:'100%', marginBottom: '-7px' }}>
              <DragIndicatorIcon style={{transform: "rotate(-90deg)", color:'#DAE0E2'}} fontSize="small"/>
            </div>
          
            <Accordion onChange={()=>{handleExpand(i)}} expanded={questions[i].open}>
              <AccordionSummary            
                aria-controls="panel1a-content"
                id="panel1a-header"
                elevation={1} style={{width:'100%'}}
              >
                { !questions[i].open ? (
              <div style={{display: 'flex',flexDirection:'column', alignItems:'flex-start', marginLeft: '3px', paddingTop: '15px', paddingBottom: '15px'}}>
                {/* <TextField id="standard-basic" label=" " value="Question" InputProps={{ disableUnderline: true }} />  */}
                
                <Typography variant="subtitle1" style={{marginLeft: '0px'}}>{i+1}.  {ques.questionText}</Typography>


                {ques.questionImage !==""?(
                  <div>
                    <img src={ques.questionImage} width="400px" height="auto" /><br></br><br></br>
                  </div>
                ): "" }
                
                {ques.options.map((op, j)=>(
                 
                 <div key={j}>
                   <div style={{display: 'flex'}}>
                    <FormControlLabel disabled control={<Radio style={{marginRight: '3px', }} />} label={
                        <Typography style={{color: '#555555'}}>
                          {ques.options[j].optionText}
                        </Typography>
                      } />
                   </div>

                  <div>
                    {op.optionImage !==""?(
                      <img src={op.optionImage} width="160px" height="auto" />
                    ): "" }
                  </div>
                 </div>
                ))}  
              </div>            
              ): ""}   
              </AccordionSummary>

              <AccordionDetails>
              <div style={{display: 'flex',flexDirection:'column', alignItems:'flex-start', marginLeft: '15px', marginTop:'-15px'}}>
                <div style={{display:'flex', width: '100%', justifyContent: 'space-between'}}>
                  <Typography style={{marginTop:'20px'}}>{i+1}.</Typography>
                  <TextField 
                        fullWidth={true} 
                        placeholder="Question Text" 
                        style={{marginBottom: '18px'}}  
                        rows={2}
                        rowsMax={20}
                        multiline={true}

                        value={ques.questionText}
                        variant="filled"
                      onChange={(e)=>{handleQuestionValue(e.target.value, i)}}
                  />
                  <IconButton aria-label="upload image" onClick={()=>{uploadImage(i, null)}}>
                        <CropOriginalIcon />
                  </IconButton>
                </div>

                <div>
                     {
                       checkImageHereOrNotForQuestion(ques.questionImage) ? (
                        <div>
                            <div style={{width:'150px', display: 'flex', alignItems:'flex-start', paddingLeft:'20px'}}>
                            <img src={ques.questionImage} width="150px" height="auto"/>
                            <IconButton style={{marginLeft: '-15px', marginTop: '-15px',zIndex:999, backgroundColor: 'lightgrey', color:'grey'}} 
                                        size="small"
                                        onClick={()=>{
                                          updateImageLink("", {question: i, option: null})
                                        }}>
                              <CloseIcon />
                            </IconButton>
                            </div>
                        </div>
                       ): ""
                     }
                </div>
                
                <div style={{width: '100%'}}>
                {ques.options.map((op, j)=>(
                 
                 <div key={j}>
                      <div  style={{display:'flex', flexDirection:'row', marginLeft:'-12.5px', justifyContent: 'space-between', paddingTop: '5px', paddingBottom: '5px'}}>

                          <Radio disabled /> 
                          <TextField 
                            fullWidth={true} 
                            placeholder="Option text" 
                            style={{marginTop: '5px'}} 
                            value={ques.options[j].optionText}
                            onChange={(e)=>{handleOptionValue(e.target.value, i, j)}}
                          />

                          <IconButton aria-label="upload image" onClick={()=>{uploadImage(i, j)}}>
                            <CropOriginalIcon />
                          </IconButton>

                          <IconButton aria-label="delete" onClick={()=>{removeOption(i, j)}}>
                            <CloseIcon />
                          </IconButton>
                          </div>

                          <div>
                          {
                            checkImageHereOrNotForOption(op.optionImage) ? (
                            <div>
                              <div style={{width:'150px', display: 'flex', alignItems:'flex-start', paddingLeft:'20px'}}>
                                <img src={op.optionImage} width="90px" height="auto"/>
                                
                                <IconButton style={{marginLeft: '-15px', marginTop: '-15px',zIndex:999, backgroundColor: 'lightgrey', color:'grey'}}
                                            size="small"
                                            onClick={()=>{
                                              updateImageLink("", {question: i, option: j})
                                            }}
                                            >
                                  <CloseIcon />
                                </IconButton>
                              </div>
                              <br></br>
                              <br></br>  
                            </div>
                            ): ""
                          }
                          </div>
                 </div>
                ))}  
                </div>  
                
                
                {ques.options.length < 5 ? (
                  <div>
                  <FormControlLabel disabled control={<Radio />} label={
                    <Button size="small" onClick={()=>{addOption(i)}} style={{textTransform: 'none', marginLeft:"-5px"}}>
                      Add Option
                    </Button>
                  } /> 
                  </div>
                ): ""}

                <br></br>
                <br></br>

                <Typography variant="body2" style={{color: 'grey'}}>You can add maximum 5 options. If you want to add more then change in settings. Multiple choice single option is availible</Typography>
              </div>
              </AccordionDetails>

              <Divider />
              
              <AccordionActions>               
                    <IconButton aria-label="View" onClick={()=>{showAsQuestion(i)}}>
                      <VisibilityIcon />
                    </IconButton>

                    <IconButton aria-label="Copy" onClick={()=>{copyQuestion(i)}}>
                      <FilterNoneIcon />
                    </IconButton>
                    <Divider orientation="vertical" flexItem/>

                    <IconButton aria-label="delete" onClick={()=>{deleteQuestion(i)}}>
                      <DeleteOutlineIcon />
                    </IconButton>

                    <IconButton aria-label="Image">
                      <MoreVertIcon />
                    </IconButton>
              </AccordionActions>
            </Accordion>
          </div>
      </div>
                    </div>
                  )}
      </Draggable>
      
     )
    )
  }




  return (
       <div style={{marginTop:'15px', marginBottom: '7px', paddingBottom:"30px"}}>
           <Grid
            container
            direction="column"
            justify="center"
            alignItems="center"
            >
              {loadingFormData ? (<CircularProgress />):""}
              
             <Grid item xs={12} sm={5} style={{width: '100%'}}>
                 
                  <Grid style={{borderTop: '10px solid teal', borderRadius: 10}}>
                      <div>
                          <div>
                            <Paper elevation={2} style={{width:'100%'}}>
                              <div style={{display: 'flex',flexDirection:'column', alignItems:'flex-start', marginLeft: '15px', paddingTop: '20px', paddingBottom: '20px'}}>
                                <Typography variant="h4" style={{fontFamily:'sans-serif Roboto', marginBottom:"15px"}}>
                                  {formData.name}
                                </Typography>
                                <Typography variant="subtitle1">{formData.description}</Typography>
                              </div>
                            </Paper>
                          </div> 
                      </div>       
                  </Grid>  

                  <Grid style={{paddingTop: '10px'}}>
                    <div>
                    <ImageUplaodModel handleImagePopOpen={openUploadImagePop} handleImagePopClose={()=>{setOpenUploadImagePop(false)}} updateImageLink={updateImageLink} contextData={imageContextData}/>

                    <DragDropContext onDragEnd={onDragEnd}>
                      <Droppable droppableId="droppable">
                        {(provided, snapshot) => (
                          <div
                            {...provided.droppableProps}
                            ref={provided.innerRef}
                          >
                            {questionsUI()}

                            {provided.placeholder}
                          </div>
                        )}
                      </Droppable>
                    </DragDropContext>
                    <div>                       
                        <Button
                          variant="contained"
                          
                          onClick={addMoreQuestionField}
                          endIcon={<AddCircleIcon />}
                          style={{margin: '5px'}}
                        >Add Question </Button>

                        <Button
                          variant="contained"
                          color="primary"
                          onClick={saveQuestions}
                          style={{margin: '15px'}}
                          endIcon={<SaveIcon />}
                        >Save Questions </Button>
                      </div>
                    </div>
                  </Grid>        
              </Grid>           
           </Grid>
       </div>
  );
}
Example #12
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function FlipShuffleStep({
  images,
  originalOrder,
  order,
  onShuffle,
  onManualShuffle,
  onReset,
}) {
  const {t} = useTranslation()
  return (
    <FlipStep alignSelf="stretch">
      <FlipStepHeader>
        <FlipStepTitle>{t('Shuffle images')}</FlipStepTitle>
        <FlipStepSubtitle>
          {t('Shuffle images in order to make a nonsense sequence of images')}
        </FlipStepSubtitle>
      </FlipStepHeader>
      <Stack isInline spacing={10} align="center" mx="auto">
        <Stack isInline spacing={10} justify="center">
          <FlipImageList>
            {originalOrder.map((num, idx) => (
              <FlipImageListItem
                key={num}
                src={images[num]}
                isFirst={idx === 0}
                isLast={idx === images.length - 1}
                opacity={0.3}
              />
            ))}
          </FlipImageList>
          <FlipImageList>
            <DragDropContext
              onDragEnd={result => {
                if (
                  result.destination &&
                  result.destination.index !== result.source.index
                ) {
                  onManualShuffle(
                    reorder(
                      order,
                      result.source.index,
                      result.destination.index
                    )
                  )
                }
              }}
            >
              <Droppable droppableId="flip-shuffle">
                {provided => (
                  <div ref={provided.innerRef} {...provided.droppableProps}>
                    {order.map((num, idx) => (
                      <DraggableItem
                        key={num}
                        draggableId={`pic-${num}`}
                        index={idx}
                      >
                        <Box position="relative">
                          <Flex
                            align="center"
                            justify="center"
                            bg="brandGray.080"
                            size={8}
                            rounded="md"
                            position="absolute"
                            top={1}
                            right={1}
                            zIndex={1}
                          >
                            <MoveIcon boxSize={5} color="white" />
                          </Flex>
                          <FlipImageListItem
                            isFirst={idx === 0}
                            isLast={idx === images.length - 1}
                            src={images[num]}
                          />
                        </Box>
                      </DraggableItem>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
          </FlipImageList>
        </Stack>
        <Stack spacing={1}>
          <IconButton icon={<CycleIcon boxSize={5} />} onClick={onShuffle}>
            {t('Shuffle images')}
          </IconButton>
          <IconButton icon={<UndoIcon boxSize={5} />} onClick={onReset}>
            {t('Reset to default')}
          </IconButton>
        </Stack>
      </Stack>
    </FlipStep>
  )
}
Example #13
Source File: slides-order.js    From horondi_admin with MIT License 4 votes vote down vote up
SlidesOrder = (props) => {
  const styles = useStyles();
  const commonStyles = useCommonStyles();

  const dispatch = useDispatch();

  const { drugAndDropList } = props;
  const [dragged, setDragged] = useState(true);
  const [data, setData] = useState(null);
  const { slideOrderTitle } = config.titles.homePageSliderTitle;
  const { SAVE_SLIDE_ORDER } = config.buttonTitles;

  const { rowsPerPage } = useSelector(({ Table }) => ({
    rowsPerPage: Table.pagination.rowsPerPage
  }));

  useEffect(() => {
    if (drugAndDropList.length) setData(convertSliderData(drugAndDropList));
  }, [drugAndDropList]);

  const onDragEnd = (result) => {
    const { destination, source } = result;

    if (!destination) {
      return;
    }

    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }

    const home = data[source.droppableId];
    const foreign = data[destination.droppableId];
    if (home === foreign) {
      const newTaskIds = Array.from(home.items);
      const [removedItem] = newTaskIds.splice(source.index, 1);
      newTaskIds.splice(destination.index, 0, removedItem);

      const newItemObject = {
        ...home,
        items: newTaskIds
      };

      const newObjectState = {
        ...data,
        [newItemObject.title]: newItemObject
      };

      setDragged(false);
      setData(newObjectState);
      return;
    }
    const homeTaskIds = Array.from(home.items);
    const [removed] = homeTaskIds.splice(source.index, 1);
    const newHome = {
      ...home,
      items: homeTaskIds
    };

    const foreignTaskIds = Array.from(foreign.items);
    foreignTaskIds.splice(destination.index, 0, removed);
    const newForeign = {
      ...foreign,
      items: foreignTaskIds
    };

    const newState = {
      ...data,
      [newHome.title]: newHome,
      [newForeign.title]: newForeign
    };
    setDragged(false);
    setData(newState);
  };

  const saveHandler = () => {
    const available = [];
    const nonAvailable = [];
    Object.entries(data).forEach(([key, value]) => {
      if (key === 'available') {
        value.items.forEach((availableSlide, index) => {
          available.push({
            id: availableSlide._id,
            slide: { ...availableSlide, order: +index + 1, show: true }
          });
        });
      }
      if (key === 'nonAvailable') {
        value.items.forEach((nonAvailableSlide) => {
          nonAvailable.push({
            id: nonAvailableSlide._id,
            slide: { ...nonAvailableSlide, order: 0, show: false }
          });
        });
      }
    });
    const newSlideItems = [...available, ...nonAvailable];
    newSlideItems.forEach((item) =>
      dispatch(
        updateSlidesOrder({
          id: item.id,
          slide: {
            order: item.slide.order,
            show: item.slide.show,
            link: item.slide.link,
            description: item.slide.description,
            title: item.slide.title
          }
        })
      )
    );
    const arrayToStore = newSlideItems.map((el) => el.slide);
    arrayToStore.length = rowsPerPage;
    dispatch(setSlides(arrayToStore));
  };

  return (
    <Paper elevation={10}>
      <div className={commonStyles.container}>
        <div className={commonStyles.adminHeader}>
          <Typography variant='h1' className={commonStyles.materialTitle}>
            {slideOrderTitle}
          </Typography>
          <div>
            <StandardButton
              className={styles.saveButton}
              data-cy='save'
              onClickHandler={saveHandler}
              title={SAVE_SLIDE_ORDER}
              disabled={dragged}
              type='button'
            />
          </div>
        </div>
        <DragDropContext onDragEnd={onDragEnd}>
          <div style={{}}>
            {data &&
              data.columnData.map((col) => (
                <Column
                  key={data[col].title}
                  column={data[col]}
                  tasks={data[col].items}
                />
              ))}
          </div>
        </DragDropContext>
      </div>
    </Paper>
  );
}
Example #14
Source File: TodoList.jsx    From 4IZ268-2021-2022-ZS with MIT License 4 votes vote down vote up
function TodoList() {
  const [todos, setTodos] = useState([])
  const [isOpen, setIsOpen] = useState(false)
  const [input, setInput] = useState('')

  // restore Todos from localStorage
  useEffect(() => {
    const restored = localStorage.getItem('todos')

    restored && setTodos(JSON.parse(restored))
  }, [])

  // save Todos to localStorage
  useEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos))
  }, [todos])

  function handleOpenList() {
    setIsOpen(!isOpen)
  }

  function handleInput(e) {
    const input = e.target.value
    if (input.length < 30) {
      setInput(input)
    }
  }

  function handleSubmit(e) {
    const input = e.target.value

    if (e.code === 'Enter' && input) {
      setTodos([
        ...todos,
        {
          task: input,
          completed: false,
        },
      ])

      setInput('')
    }
  }

  function toggleCompletion(idx) {
    const newTodos = [...todos]
    newTodos[idx].completed = !newTodos[idx].completed
    setTodos(newTodos)
  }

  function removeTodo(idx) {
    const newTodos = [...todos]
    newTodos.splice(idx, 1)
    setTodos(newTodos)
  }

  const onDragEnd = useCallback(
    (result) => {
      // dropped outside the list
      if (!result.destination) {
        return
      }

      const newState = reorder(
        todos,
        result.source.index,
        result.destination.index
      )

      setTodos(newState)
    },
    [todos]
  )

  function reorder(list, startIndex, endIndex) {
    const result = Array.from(list)
    const [removed] = result.splice(startIndex, 1)
    result.splice(endIndex, 0, removed)

    return result
  }

  return (
    <div className='relative'>
      <div
        className={`absolute ${
          isOpen ? 'bottom-14 opacity-100' : 'bottom-12 opacity-0'
        } right-4 px-7 pt-5 pb-8 bg-black/60 backdrop-blur-sm rounded-lg transition-all`}>
        <DragDropContext onDragEnd={onDragEnd}>
          <Droppable droppableId='droppable'>
            {(provided, snapshot) => (
              <div {...provided.droppableProps} ref={provided.innerRef}>
                {todos.map((item, idx) => (
                  <Draggable
                    key={item.task}
                    draggableId={item.task}
                    index={idx}>
                    {(provided, snapshot) => (
                      <div
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}>
                        <Todo
                          todo={item}
                          handleCompletion={(idx) => toggleCompletion(idx)}
                          handleRemoval={(idx) => removeTodo(idx)}
                        />
                      </div>
                    )}
                  </Draggable>
                ))}
                {provided.placeholder}
              </div>
            )}
          </Droppable>
        </DragDropContext>
        <input
          className='w-56 bg-transparent border-b border-solid border-white
              opacity-60 hover:opacity-80 focus:opacity-100 focus:outline-none
              transition-colors mt-4 mx-4'
          type='text'
          value={input}
          placeholder='New Todo'
          onChange={handleInput}
          onKeyPress={handleSubmit}
        />
      </div>

      <button
        onClick={handleOpenList}
        className='text-xl font-medium px-4 py-3 opacity-70 hover:opacity-90 transition-opacity'>
        Todos
      </button>
    </div>
  )
}
Example #15
Source File: TaskBoard.js    From fokus with GNU General Public License v3.0 4 votes vote down vote up
export function TaskBoard() {
    const tasks = useSelector((state) => state.tasks.taskArray);
    const meta = useSelector((state) => state.tasks.meta);
    let focussedTask = meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex] : null;
    const dispatch = useDispatch();

    function handleOnDragEnd(result) {
        if (!result.destination) return;

        let items = [...tasks.map((i) => ({ ...i }))];
        const [reorderedItem] = items.splice(result.source.index, 1);
        items.splice(result.destination.index, 0, reorderedItem);

        let i = result.source.index;
        let direction = result.destination.index > result.source.index; // direction true means moving right & swapping
        // below is logic to reset globalKeys to maintain correct sort order.
        while (i != result.destination.index) {
            if (direction) {
                items[i].globalKey = tasks[i].globalKey;
                i++;
            } else {
                items[i].globalKey = tasks[i].globalKey;
                i--;
            }
            if (i == result.destination.index) {
                items[i].globalKey = tasks[i].globalKey;
            }
        }

        if (meta.focussedTaskIndex !== -1) {
            let greaterIndex = Math.max(result.destination.index, result.source.index);
            let smallerIndex = Math.min(result.destination.index, result.source.index);

            if (result.source.index === meta.focussedTaskIndex) {
                dispatch(focusOnTask(result.destination.index));
            } else if (meta.focussedTaskIndex >= smallerIndex && meta.focussedTaskIndex <= greaterIndex) {
                if (result.destination.index > result.source.index) {
                    dispatch(focusOnTask(meta.focussedTaskIndex - 1)); // -1
                } else {
                    dispatch(focusOnTask(meta.focussedTaskIndex + 1)); // +1
                }
            }
        }

        dispatch(updateOrder(items)); // order is imp. focus then updateOrder
    }

    function getFlipKey() {
        let flipKey = "";
        tasks.forEach((i) => {
            flipKey += `${i.globalKey}`;
        });
        flipKey += `${meta.completedTaskStartIndex}`;
        return flipKey;
    }

    function isFocussed(id) {
        if (focussedTask !== null && focussedTask.id === id) return true;
        return false;
    }

    // input has both onChange and onKeyDown - can be optimised by using one and combining

    return (
        <TaskBoardContainer>
            <TaskInput focussedTaskIndex={meta.focussedTaskIndex} />
            {tasks.length === 0 ? <NoTasks /> : tasks.length === meta.completedTasksCount && <NoTasks allCompleted={true} />}
            <Flipper flipKey={getFlipKey()}>
                <DragDropContext onDragEnd={handleOnDragEnd}>
                    <Droppable droppableId="dropArea">
                        {(provided) => (
                            <div {...provided.droppableProps} ref={provided.innerRef}>
                                {tasks.map((i, index) =>
                                    !i.isCompleted ? (
                                        <Draggable isDragDisabled={i.isCompleted} key={i.id} draggableId={`${i.id}`} index={index}>
                                            {(provided2) => (
                                                <TaskCard
                                                    focussedTaskIndex={meta.focussedTaskIndex}
                                                    focussedTaskGlobalKey={meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex].globalKey : -1}
                                                    taskIndex={index}
                                                    forwardRBDProvided={provided2}
                                                    task={i}
                                                    isFocussed={isFocussed(i.id)}
                                                />
                                            )}
                                        </Draggable>
                                    ) : (
                                        ""
                                    )
                                )}
                                {provided.placeholder}
                            </div>
                        )}
                    </Droppable>
                </DragDropContext>

                {meta.completedTaskStartIndex !== -1 && <Divider />}

                {meta.showCompletedTasks &&
                    tasks.map((i, index) =>
                        i.isCompleted ? (
                            <TaskCard
                                focussedTaskIndex={meta.focussedTaskIndex}
                                focussedTaskGlobalKey={meta.focussedTaskIndex !== -1 ? tasks[meta.focussedTaskIndex].globalKey : -1}
                                taskIndex={index}
                                key={i.id}
                                forwardRBDProvided={{ innerRef: null }}
                                task={i}
                                isFocussed={isFocussed(i.id)}
                            />
                        ) : (
                            ""
                        )
                    )}
            </Flipper>
            <EmptySpace />
        </TaskBoardContainer>
    );
}
Example #16
Source File: tableDrag.js    From camel-store-admin with Apache License 2.0 4 votes vote down vote up
render() {
    const { columns, dataSource, restProps, total } = this.conversionObject()
    const { scroll, pagination } = restProps;
    const { pageSize, offsetWidthBody } = this.state
    const widthtable = scroll && scroll.x ? ( offsetWidthBody > scroll.x ? offsetWidthBody : scroll.x) : 'auto'

    return (
      <div className={styles.dragTable}>
      {/*<Table*/}
        {/*columns={columns}*/}
        {/*dataSource={dataSource}*/}
        {/*components={this.components}*/}
        {/*pagination={false}*/}
        {/*size='small'*/}
        {/*onRow={(record, index) => ({*/}
          {/*index,*/}
          {/*moveRow: this.moveRow,*/}
        {/*})}*/}
        {/*{...restProps}*/}
      {/*/>*/}
        <DragDropContext onDragEnd={this.onDragEnd}>
        <div className="ant-table-wrapper">
          <div className="ant-spin-nested-loading">
            <div className="ant-spin-container">
              <div className="ant-table ant-table-small ant-table-scroll-position-left">
                <div className="ant-table-content">
                  <div className="ant-table-body" id="tableDragbody" style={ scroll && scroll.x ? {overflowX: 'scroll'} : {}}>
                    <table style={isNaN(widthtable) ? {} : {width:widthtable + 'px'}} id="tableDrag">
                      <thead className="ant-table-thead">
                      <tr>
                        { columns.map(item => {
                          return (<th style={item.width ? { width: `${item.width}px`,userSelect:'none'} : {userSelect:'none'}}><div>{item.title}</div></th>)
                        })}
                      </tr></thead>
                      <Droppable droppableId="droppable">
                        {(provided, snapshot) => (
                          <tbody className="ant-table-tbody" ref={provided.innerRef}>
                            {dataSource.length > 0 && dataSource.map((item, index) => (
                              <Draggable key={item.key} draggableId={item.key} index={index}>
                                {(provided, snapshot) => (
                                  <tr className="ant-table-row ant-table-row-level-0" data-row-key={index}
                                    ref={provided.innerRef}
                                    {...provided.draggableProps}
                                    {...provided.dragHandleProps}
                                    style={getItemStyle(
                                      snapshot.isDragging,
                                      provided.draggableProps.style
                                    )}
                                  >
                                    {columns.map(item_in => {
                                      return (
                                        <td style={item_in.width ? { width: `${item_in.width}px`,userSelect:'none'} : {userSelect:'none'}}>
                                          {item_in.render && item_in.render(item[item_in.dataIndex],item) || item[item_in.dataIndex]}
                                        </td>
                                      )
                                    })}
                                  </tr>
                                )}
                              </Draggable>
                            ))}
                            {provided.placeholder}
                          </tbody>
                        )}
                      </Droppable>
                    </table>
                  </div>
                  {dataSource.length === 0 && <div className="ant-table-placeholder"><Empty /></div>}
                </div>
              </div>
            </div>
          </div>
        </div>
        </DragDropContext>
        { pagination &&
          <Row><Col style={{textAlign:'right', marginTop: 10, marginBottom: 10 }}>
            <Pagination pageSize={pageSize} size="small" total={total} showSizeChanger
                        onChange={this.pageChange} onShowSizeChange={this.pageSizeChange}/>
          </Col></Row> }
      </div>
    );
  }
Example #17
Source File: Board.js    From trello-clone with MIT License 4 votes vote down vote up
Board = (props) => {
    const { id } = props.match.params;
    const [addingList, setAddingList] = useState(false);
    const { data: board, setData: setBoard, loading } = useAxiosGet(
        `/boards/${id}/`
    );

    const { setBoardContext } = useContext(globalContext);
    useEffect(() => {
        if (board) {
            setBoardContext(board, setBoard);
        }
    }, [board]);

    useDocumentTitle(board ? `${board.title} | Trello` : "");
    useBlurSetState(".board__create-list-form", addingList, setAddingList);
    const [editingTitle, setEditingTitle] = useState(false);
    useBlurSetState(".board__title-edit", editingTitle, setEditingTitle);

    const [isBackgroundDark, setIsBackgroundDark] = useState(false);
    useEffect(handleBackgroundBrightness(board, setIsBackgroundDark), [board]);

    if (!board && loading) return null;
    if (!board && !loading) return <Error404 />;
    return (
        <div className="board" style={getBoardStyle(board)}>
            {!editingTitle ? (
                <p
                    className="board__title"
                    onClick={() => setEditingTitle(true)}
                    style={isBackgroundDark ? { color: "white" } : null}
                >
                    {board.title}
                </p>
            ) : (
                <EditBoard
                    setEditingTitle={setEditingTitle}
                    board={board}
                    setBoard={setBoard}
                />
            )}
            <p className="board__subtitle">{board.owner.title}</p>
            <DragDropContext onDragEnd={onDragEnd(board, setBoard)}>
                <Droppable
                    droppableId={"board" + board.id.toString()}
                    direction="horizontal"
                    type="list"
                >
                    {(provided) => (
                        <div
                            className="board__lists"
                            ref={provided.innerRef}
                            {...provided.droppableProps}
                        >
                            {board.lists.map((list, index) => (
                                <List
                                    list={list}
                                    index={index}
                                    key={uuidv4()}
                                />
                            ))}
                            {provided.placeholder}
                            {addingList ? (
                                <CreateList
                                    board={board}
                                    setBoard={setBoard}
                                    setAddingList={setAddingList}
                                />
                            ) : (
                                <button
                                    className="btn board__create-list"
                                    onClick={() => setAddingList(true)}
                                    style={
                                        board.lists.length === 0
                                            ? { marginLeft: 0 }
                                            : null
                                    }
                                >
                                    <i className="fal fa-plus"></i>
                                    Add{" "}
                                    {board.lists.length === 0
                                        ? "a"
                                        : "another"}{" "}
                                    list
                                </button>
                            )}
                        </div>
                    )}
                </Droppable>
            </DragDropContext>
        </div>
    );
}
Example #18
Source File: Board.js    From ytx-card-game with MIT License 4 votes vote down vote up
Board = (props) => {
	const { state, dispatch } = useContext(store)
	const isGamePaused = () => state.game && state.game.gamePaused
	const [allyCards, setAllyCards] = useState({
		[ALLY_TYPES.hand]: [],
		[ALLY_TYPES.field]: [],
	})

	useLayoutEffect(() => {
		if (state.game) {
			if (state.playerNumber === 1) {
				setAllyCards({
					[ALLY_TYPES.hand]: [...state.game.player1.hand],
					[ALLY_TYPES.field]: [...state.game.player1.field],
				})
			} else {
				setAllyCards({
					[ALLY_TYPES.hand]: [...state.game.player2.hand],
					[ALLY_TYPES.field]: [...state.game.player2.field],
				})
			}
		}
	}, [state.game])

	const getAllyStateType = (droppableId) => {
		return allyCards[droppableId]
	}

	const invokeCard = (card) => {
		console.log('invoke card', card)
		if (!card.isInvoked) {
			let me
			if (state.playerNumber === 1) {
				me = state.game.player1
			} else {
				me = state.game.player2
			}
			// Invokes a card into the field and updates ally hand with a new deep copy
			if (me.field.length >= FIELD_SIZE) {
				return dispatch({
					type: 'SET_ERROR',
					payload: {
						error: 'The field is full',
					},
				})
			}
			if (card.cost > me.energy) {
				return dispatch({
					type: 'SET_ERROR',
					payload: {
						error:
							"You don't have enough energy to invoke this card",
					},
				})
			}
			card.isInvoked = true
			state.socket.emit('invoke-card', {
				game: state.game,
				card,
			})
		}
	}

	const onDragEnd = useCallback(
		(result) => {
			const { source, destination } = result
			if (!destination) {
				return
			}
			let allyState = getAllyStateType(source.droppableId)
			const isEnoughEnergyToInvoke =
				state.playerNumber === 1
					? state.game.player1.energy
					: state.game.player2.energy
			console.log(
				isEnoughEnergyToInvoke,
				allyState.cost,
				'energy',
				state.playerNumber,
				state.game.player1.energy,
				state.game.player2.energy,
			)
			if (isEnoughEnergyToInvoke < allyState[source.index].cost) {
				return
			}
			if (source.droppableId === destination.droppableId) {
				const items = reorder(
					allyState,
					source.index,
					destination.index,
				)
				setAllyCards({ ...allyCards, [source.droppableId]: items })
			} else {
				//invoke card
				invokeCard(allyCards[ALLY_TYPES.hand][source.index])
				const result = move(
					getAllyStateType(source.droppableId),
					getAllyStateType(destination.droppableId),
					source,
					destination,
				)
				setAllyCards({
					[ALLY_TYPES.hand]: result[ALLY_TYPES.hand],
					[ALLY_TYPES.field]: result[ALLY_TYPES.field],
				})
			}
		},
		[state.game, allyCards],
	)

	return (
		<Page>
			<ResultMsg
				winner={state.gameOver && state.areYouTheWinner}
				loser={state.gameOver && !state.areYouTheWinner}
			>
				{state.gameOver && state.areYouTheWinner
					? 'Congratulations! You are the winner!'
					: state.gameOver && !state.areYouTheWinner
						? 'You lost! Better luck next time!'
						: null}
			</ResultMsg>
			{/* <p>Turn: {state.game ? state.game.currentTurnNumber : 0}</p>
			<p>Timer: {props.turnCountdownTimer}</p> */}
			<ExitLink hidden={!state.gameOver} to="/">
				Exit
			</ExitLink>
			{state.game ? (
				<Game className="game">
					<EnemyDeck>Enemy's <br /> Deck</EnemyDeck>
					<YourDeck>Your <br /> Deck</YourDeck>
					<EnemyStatsBox
						className={
							state.isAttackMode
								? 'enemy-stats attack-mode'
								: 'enemy-stats'
						}
						onClick={() => {
							if (state.isAttackMode) props.attackDirectly()
						}}
					>
						<p>Enemy</p>
						<p>
							{state.playerNumber === 1
								? state.game.player2.life
								: state.game.player1.life}
							<FaHeart />
						</p>
						<p>
							{state.playerNumber === 1
								? state.game.player2.energy
								: state.game.player1.energy}
							<FaBolt />
						</p>
					</EnemyStatsBox>
					<AllyStatsBox className="my-stats">
						<p>You</p>
						<p>
							{state.playerNumber === 1
								? state.game.player1.life
								: state.game.player2.life}
							<FaHeart />
						</p>
						<p>
							{state.playerNumber === 1
								? state.game.player1.energy
								: state.game.player2.energy}
							<FaBolt />
						</p>
					</AllyStatsBox>
					<CardContainer className="cards-container enemy-cards-container">
						{state.visualEnemyHand}
					</CardContainer>
					<Field className="field">
						<DragDropContext onDragEnd={onDragEnd}>
							<EnemyField
								className={
									state.isAttackMode
										? 'enemy-field attack-mode'
										: 'enemy-field'
								}
							>
								{state.enemyFieldHtml}
							</EnemyField>
							<FieldContainer top >
								<Droppable
									droppableId={`${ALLY_TYPES.field}`}
									direction="horizontal"
								>
									{(provided, snapshot) => (
										<CardPanel
											ref={provided.innerRef}
											isDraggingOver={snapshot.isDraggingOver}
										>
											{allyCards[ALLY_TYPES.field].map(
												(allyFieldCard, index) => (
													<Draggable
														key={index}
														draggableId={`allyFieldCard${index}`}
														index={index}
														isDragDisabled={true}
													>
														{(
															provided,
															snapshot,
														) => (
															<div
																ref={
																	provided.innerRef
																}
																{...provided.draggableProps}
																{...provided.dragHandleProps}
															>
																<BoardCard
																	{...allyFieldCard}
																/>
															</div>
														)}
													</Draggable>
												),
											)}
											{provided.placeholder}
										</CardPanel>
									)}
								</Droppable>
							</FieldContainer>
							<FieldContainer bottom>
								<Droppable
									droppableId={`${ALLY_TYPES.hand}`}
									direction="horizontal"
								>
									{(provided, snapshot) => (
										<CardPanel
											ref={provided.innerRef}
											// isDraggingOver={snapshot.isDraggingOver}
											outter
										>
											{allyCards[ALLY_TYPES.hand].map(
												(allyHandCard, index) => (
													<Draggable
														key={index}
														draggableId={`allyHand${index}`}
														index={index}
														isDragDisabled={
															state.playerNumber !==
															state.game
																.currentPlayerTurn
														}
													>
														{(
															provided,
															snapshot,
														) => (
															<div
																ref={
																	provided.innerRef
																}
																{...provided.draggableProps}
																{...provided.dragHandleProps}
															>
																<BoardCard
																	{...allyHandCard}
																/>
															</div>
														)}
													</Draggable>
												),
											)}
											{provided.placeholder}
										</CardPanel>
									)}
								</Droppable>
							</FieldContainer>
						</DragDropContext>
					</Field>
					<Button
						className="end-turn"
						disabled={state.isOtherPlayerTurn || isGamePaused()}
						onClick={() => {
							props.endTurn()
						}}
					>
						End Turn
					</Button>
					<Button
						className="surrender"
						style={{
							backgroundColor: 'red',
						}}
						disabled={isGamePaused()}
						onClick={() => {
							props.surrender()
						}}
					>
						Surrender
					</Button>
				</Game>
			) : (
					<p>Game loading...</p>
				)}
		</Page>
	)
}
Example #19
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function FlipEditorStep({
  keywords,
  showTranslation,
  originalOrder,
  images,
  onChangeImage,
  onChangeOriginalOrder,
  onPainting,
}) {
  const {t} = useTranslation()

  const [currentIndex, setCurrentIdx] = React.useState(0)

  const {words, translations} = keywords

  const hasBothTranslations = translations.reduce(
    (acc, {length}) => !!length && acc,
    true
  )

  return (
    <FlipStep>
      <FlipStepHeader>
        <FlipStepTitle>{t('Select 4 images to tell your story')}</FlipStepTitle>
        <FlipStepSubtitle>
          {t(`Use keywords for the story`)}{' '}
          <Text as="mark">
            {formatKeywords(
              hasBothTranslations && showTranslation
                ? translations.map(([{name, desc}]) => ({
                    name,
                    desc,
                  }))
                : words
            )}
          </Text>{' '}
          {t(`and template "Before
          – Something happens – After"`)}
          .
        </FlipStepSubtitle>
      </FlipStepHeader>
      <Stack isInline spacing={10}>
        <FlipImageList>
          <DragDropContext
            onDragEnd={result => {
              if (
                result.destination &&
                result.destination.index !== result.source.index
              ) {
                setCurrentIdx(result.destination.index)

                onChangeOriginalOrder(
                  reorder(
                    originalOrder,
                    result.source.index,
                    result.destination.index
                  )
                )
              }
            }}
          >
            <Droppable droppableId="flip-editor">
              {provided => (
                <div ref={provided.innerRef} {...provided.droppableProps}>
                  {originalOrder.map((num, idx) => (
                    <DraggableItem
                      key={num}
                      draggableId={`image-${num}`}
                      index={idx}
                    >
                      <SelectableItem
                        isActive={idx === currentIndex}
                        isFirst={idx === 0}
                        isLast={idx === images.length - 1}
                        onClick={() => setCurrentIdx(idx)}
                      >
                        <FlipImageListItem
                          isFirst={idx === 0}
                          isLast={idx === images.length - 1}
                          src={images[num]}
                        />
                      </SelectableItem>
                    </DraggableItem>
                  ))}
                  {provided.placeholder}
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </FlipImageList>
        <Box>
          {originalOrder.map((num, idx) => (
            <FlipEditor
              key={num}
              idx={num}
              visible={currentIndex === idx}
              src={images[num]}
              onChange={url => {
                onChangeImage(url, num)
              }}
              onChanging={onPainting}
            />
          ))}
        </Box>
      </Stack>
    </FlipStep>
  )
}
Example #20
Source File: stepDndList.js    From pathways with GNU General Public License v3.0 4 votes vote down vote up
render() {
        const stepData = this.props.steps
        const steps = this.props.stepOrder.map((stepId, index) => {
            const currentStep = stepData[stepId]
            return (
                <Step
                    key={index}
                    id={stepId}
                    index={index}
                    heading={currentStep.heading}
                    stepType={currentStep.stepType}
                    selected={currentStep.selected}
                    rating={currentStep.rating}
                    selected={currentStep.selected}
                />
            )
        })

        return (
            <div className={classes.ControlsArea}>
                <div className={classes.StepListArea}>
                    <div className={classes.StepListTitle}>
                        <p style={{ fontSize: '40px' }}>Steps</p>
                        <Button
                            aria-controls='simple-menu'
                            aria-haspopup='true'
                            onClick={this.handleClick}
                        >
                            <PlusIcon fontSize='30px' color='#555' />
                        </Button>
                        <Menu
                            id='simple-menu'
                            anchorEl={this.state.anchorEl}
                            keepMounted
                            open={Boolean(this.state.anchorEl)}
                            onClose={this.handleClose}
                        >
                            <MenuItem
                                onClick={() => this.handleClose('pathway')}
                            >
                                <div className={classes.pathwayStep}>
                                    Pathway
                                </div>
                            </MenuItem>
                            <MenuItem
                                onClick={() => this.handleClose('content')}
                            >
                                <div className={classes.contentStep}>
                                    Content
                                </div>
                            </MenuItem>
                            <MenuItem
                                onClick={() => this.handleClose('shared')}
                            >
                                <div className={classes.sharedStep}>
                                    Shared Step
                                </div>
                            </MenuItem>
                        </Menu>
                    </div>

                    <DragDropContext onDragEnd={this.onDragEnd}>
                        <Droppable droppableId='myNiggaThatsCrazy'>
                            {(provided, snapshot) => (
                                <div
                                    {...provided.droppableProps}
                                    ref={provided.innerRef}
                                    style={getListStyle(
                                        snapshot.isDraggingOver
                                    )}
                                >
                                    {steps}
                                    {provided.placeholder}
                                </div>
                            )}
                        </Droppable>
                    </DragDropContext>
                </div>
                <div className={classes.MoreControls}>
                    <div>
                        <div className={classes.MoreControlsIcon}>
                            <SaveIcon fontSize='50px' color='#102e4a' />
                        </div>
                        <div
                            className={classes.MoreControlsIcon}
                            onClick={this.setPathwayDetails}
                        >
                            <SettingsIcon fontSize='50px' color='#102e4a' />
                        </div>
                        <div className={classes.MoreControlsIcon}>
                            {/* Clicking on this icon should render a preview of the pathway */}
                            <PreviewIcon fontSize='50px' color='#102e4a' />
                        </div>
                    </div>
                    <div>
                        <div className={classes.MoreControlsIcon}>
                            <DownloadIcon fontSize='50px' color='#102e4a' />
                        </div>
                    </div>
                </div>
            </div>
        )
    }
Example #21
Source File: SearchIndex.js    From ActiveLearningStudio-react-client with GNU Affero General Public License v3.0 4 votes vote down vote up
function SearchIndex(props) {
  const { match } = props;
  const playlistBuilder = useSelector((state) => state.playlist.selectedPlaylist);
  const origPlaylist = useSelector((state) => state.playlist.playlists);
  const searchBuilder = useSelector((state) => state.search);
  const [playlist, setPlaylist] = useState();
  const [search, setSearch] = useState([]);
  const dispatch = useDispatch();
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  const move = (source, destination, droppableSource, droppableDestination) => {
    const sourceClone = Array.from(source);
    const destClone = Array.from(destination);
    const [removed] = sourceClone.splice(droppableSource.index, 1);

    destClone.splice(droppableDestination.index, 0, removed);

    const result = {};
    result[droppableSource.droppableId] = sourceClone;
    result[droppableDestination.droppableId] = destClone;

    return result;
  };

  useEffect(() => {
    setPlaylist(playlistBuilder);
  }, [playlistBuilder]);

  useEffect(() => {
    dispatch(loadProjectPlaylistsAction(match.params.projectId));
  }, []);

  useEffect(() => {
    setSearch(searchBuilder.searchResult);
    Swal.close();
  }, [searchBuilder.searchResult]);

  const onDragEnd = (result) => {
    // dropped outside the list
    const { source, destination } = result;
    if (!result.destination) {
      return;
    }
    if (source.droppableId === destination.droppableId) {
      if (source.droppableId === 'droppable2') {
        const items = reorder(
          playlist.activities,
          source.index,
          destination.index,
        );
        const updatedOrder = origPlaylist.map((play) => {
          if (String(play.id) === match.params.playlistId) {
            return { ...play, activities: items };
          }
          return play;
        });
        dispatch(reorderPlaylistsAction(match.params.projectId, origPlaylist, updatedOrder));
        setPlaylist({ ...playlist, activities: items });
      // eslint-disable-next-line
      } }
    else if (source.droppableId === 'droppable') {
      const resultHorizantal = move(
        search,
        playlist.activities,
        source,
        destination,
      );
      const updatedOrder = origPlaylist.map((play) => {
        if (String(play.id) === match.params.playlistId) {
          return { ...play, activities: resultHorizantal.droppable2 };
        }
        return play;
      });
      dispatch(reorderPlaylistsAction(match.params.projectId, origPlaylist, updatedOrder));
      setPlaylist({ ...playlist, activities: resultHorizantal.droppable2 });
      // setSearch(resultHorizantal.droppable);
    }
  };
  return (
    <div className="search-wizard">
      <h2>Search For Activity</h2>
      <div className="formik-form">
        <SearchActivity />
      </div>
      <div className="drag-activity-search">
        <div className="active-playlist">
          <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="droppable" className="search-class">
              {(provided) => (
                <div
                  {...provided.droppableProps}
                  ref={provided.innerRef}
                  // style={getListStyle(snapshot.isDraggingOver)}
                >
                  {searchBuilder.searchQuery ? (
                    <>
                      <h2>
                        Your Search Result for
                        {' '}
                        {searchBuilder.searchQuery}
                      </h2>
                      <p>Drag & drop activity to build your playlist.</p>
                    </>
                  ) : <p>Search Activity from above to use Existing.</p>}
                  {!!search.length > 0
                    ? search.map((res, index) => (
                      <Draggable
                        key={res.id}
                        draggableId={String(res.id)}
                        index={index}
                      >
                        {(provided_) => (
                          <div
                            ref={provided_.innerRef}
                            {...provided_.draggableProps}
                            {...provided_.dragHandleProps}
                          >
                            <div className="box">
                              <div className="imgbox">
                                {res.thumb_url ? (
                                  <div
                                    style={{
                                      backgroundImage: res.thumb_url.includes('pexels.com')
                                        ? `url(${res.thumb_url})`
                                        : `url(${global.config.resourceUrl}${res.thumb_url})`,
                                    }}
                                  />
                                ) : (
                                  <div
                                    style={{
                                      // eslint-disable-next-line max-len
                                      backgroundImage: 'https://images.pexels.com/photos/593158/pexels-photo-593158.jpeg?auto=compress&amp;cs=tinysrgb&amp;dpr=1&amp;fit=crop&amp;h=200&amp;w=280',
                                    }}
                                  />
                                )}
                              </div>
                              <div className="content">
                                <div className="search-content">
                                  <a
                                    href={
                                      res.model === 'Activity'
                                        ? `/activity/${res.id}/shared`
                                        : res.model === 'Playlist'
                                          ? `/playlist/${res.id}/preview/lti`
                                          : `/project/${res.id}/shared`
                                    }
                                    target="_blank"
                                    rel="noreferrer"
                                  >
                                    <h2>{res.title || res.name}</h2>
                                  </a>
                                  <ul>
                                    {res.user && (
                                      <li>
                                        by
                                        {' '}
                                        <span className="author">
                                          {res.user.first_name}
                                        </span>
                                      </li>
                                    )}
                                  </ul>
                                </div>
                              </div>
                            </div>
                          </div>
                        )}
                      </Draggable>
                    )) : <h2>{!!searchBuilder.searchQuery && <> No result found!</>}</h2>}
                </div>
              )}
            </Droppable>
            <Droppable droppableId="droppable2" className="playlist-class">
              {(provided) => (
                <div
                  {...provided.droppableProps}
                  ref={provided.innerRef}
                  // style={getListStyle(snapshot.isDraggingOver)}
                >
                  <div className="playlist-host">
                    <h6>{!!playlist && playlist.title}</h6>
                    {!!playlist && playlist.activities.map((resource, index) => (
                      <ResourceCard
                        resource={resource}
                        key={resource.id}
                        index={index}
                        playlist={playlist}
                        wizard
                      />
                    ))}
                  </div>
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </div>
      </div>
    </div>
  );
}
Example #22
Source File: FileBlock.js    From sailplane-web with GNU General Public License v3.0 4 votes vote down vote up
export function FileBlock({
  sharedFs,
  ipfs,
  directoryContents,
  setCurrentDirectory,
  currentDirectory,
  isEncrypted,
}) {
  const isSmallScreen = useIsSmallScreen();
  const dropzoneRef = useRef(null);
  const fullFileList = sortDirectoryContents(directoryContents);
  const pathSplit = currentDirectory.split('/');
  const parentSplit = pathSplit.slice(0, pathSplit.length - 1);
  const parentPath = parentSplit.join('/');
  const [isImageOpen, setIsImageOpen] = useState(false);
  const [mainSrcURL, setMainSrcURL] = useState(null);
  const [imageTitle, setImageTitle] = useState('');
  const [imageCaption, setImageCaption] = useState('');
  const updateTime = useRef({});
  const imagePath = useRef({});

  const dispatch = useDispatch();

  const isImageItem = ({ type, name }) => type === 'file' && isImageFileExt(filenameExt(name));

  const neighborImagePaths = (path) => {
    const imagePaths = fullFileList.filter(isImageItem).map(f => f.path);
    const neighborhood = [...new Set([...imagePaths, path])].sort(alphabetical);
    const index = neighborhood.indexOf(path);

    return {
      prev: neighborhood[(index + neighborhood.length - 1) % neighborhood.length],
      next: neighborhood[(index + 1) % neighborhood.length],
    };
  };

  const executer = (path, time) => (func) =>
    path === imagePath.current && time === updateTime.current && func();

  const handleUpdate = (exe) => (current, total) =>
    exe(() => setImageCaption(current === total ? '' : `Loading... [${getPercent(current, total)}%]`));

  const loadImagePath = async (path) => {
    const time = Date.now();
    imagePath.current = path;
    updateTime.current = time;
    const exe = executer(path, time);
    setMainSrcURL(null);


    exe(() => setImageTitle(sharedFs.current.fs.pathName(path)));
    const imageData = await sharedFs.current.cat(path, { handleUpdate: handleUpdate(exe) }).data();
    exe(() => setMainSrcURL(window.URL.createObjectURL(new Blob([imageData]))));
  };

  const setImageOpen = ({ path } = {}) => {
    path = path || null;
    path ? loadImagePath(path) : setMainSrcURL(path);
    setIsImageOpen(Boolean(path));
  };

  return (
    <div style={styles.container}>
      {isImageOpen && (
        <Lightbox
          prevSrc={emptyImageURL}
          nextSrc={emptyImageURL}
          mainSrc={mainSrcURL}
          onMovePrevRequest={() => loadImagePath(neighborImagePaths(imagePath.current)['prev'])}
          onMoveNextRequest={() => loadImagePath(neighborImagePaths(imagePath.current)['next'])}
          onCloseRequest={() => setImageOpen(false)}
          imageTitle={imageTitle}
          imageCaption={imageCaption}
        />
      )}
      <FolderTools
        currentDirectory={currentDirectory}
        sharedFs={sharedFs}
        setCurrentDirectory={setCurrentDirectory}
        isEncrypted={isEncrypted}
        handleOpenUpload={() => {
          dropzoneRef.current.openUpload();
        }}
      />
      <div style={styles.fileHeader}>
        <div style={{...styles.fileHeaderItem, paddingLeft: 12}}>Name</div>
        {!isSmallScreen ? (
          <>
            <div style={{...styles.fileHeaderItem, textAlign: 'right'}}>
              Size
            </div>
            <div style={{...styles.fileHeaderItem, textAlign: 'right'}}>
              Modified
            </div>
          </>
        ) : null}

        <div style={styles.fileHeaderItem} />
      </div>
      <div style={styles.dropContainer}>
        <DropZone
          sharedFs={sharedFs}
          currentDirectory={currentDirectory}
          ref={dropzoneRef}>
          <DragDropContext
            onDragEnd={async (draggable) => {
              const {combine, draggableId} = draggable;
              if (combine) {
                const fileName = sharedFs.current.fs.pathName(draggableId);
                if (
                  sharedFs.current.fs.content(combine.draggableId) !== 'dir'
                ) {
                  return;
                }

                try {
                  await sharedFs.current.move(
                    draggable.draggableId,
                    draggable.combine.draggableId,
                    fileName,
                  );
                } catch (e) {
                  dispatch(
                    setStatus({
                      message: `failed to move ${draggable.draggableId}`,
                      isError: true,
                    }),
                  );
                  delay(2000).then(() => dispatch(setStatus({})));
                }
              }
            }}>
            <Droppable
              droppableId="droppable-1"
              type="fileblock"
              isCombineEnabled={true}>
              {(provided, snapshot) => (
                <div style={styles.filesContainer}>
                  {currentDirectory !== '/r' ? (
                    <DraggableFileItem
                      fileIndex={0}
                      isParent={true}
                      key={parentPath}
                      data={{path: parentPath, type: 'dir'}}
                      sharedFs={sharedFs}
                      ipfs={ipfs}
                      setCurrentDirectory={setCurrentDirectory}
                    />
                  ) : null}
                  <div
                    ref={provided.innerRef}
                    style={
                      {
                        // backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey',
                      }
                    }
                    {...provided.droppableProps}>
                    {!directoryContents.length ? (
                      <FileDragBlock
                        handleOpenUpload={() => {
                          dropzoneRef.current.openUpload();
                        }}
                      />
                    ) : (
                      <div style={styles.files}>
                        {fullFileList.map((fileItem, index) => (
                          <DraggableFileItem
                            fileIndex={index + 1}
                            key={fileItem.path}
                            data={fileItem}
                            sharedFs={sharedFs}
                            ipfs={ipfs}
                            setCurrentDirectory={setCurrentDirectory}
                            onIconClicked={
                              isImageItem(fileItem) ? () => setImageOpen(fileItem) : null
                            }
                          />
                        ))}
                      </div>
                    )}
                    <span
                      style={{
                        display: 'none',
                      }}>
                      {provided.placeholder}
                    </span>
                  </div>
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </DropZone>
      </div>
      <StatusBar />
      <ShareDialog sharedFs={sharedFs} />
    </div>
  );
}
Example #23
Source File: projects.js    From community-forum-frontend with GNU General Public License v3.0 4 votes vote down vote up
render() {
    return (
      <div>
        <Modal show={this.state.showModal} onHide={this.handleClose} centered>
          <div className="modalbody">
            <Modal.Body>
              <TopicForm
                projectID={this.state.projectID}
                handleTopicSubmission={this.handleTopicSubmission}
              />
            </Modal.Body>
          </div>
        </Modal>
        <DragDropContext onDragEnd={this.onDragEnd}>
          <div className="projectCards">
            {this.state.categoriesArray.map((categoryID) => {
              const category = this.state.categories[categoryID._id];
              return (
                <Card
                  className="projectCard"
                  bg="light"
                  style={{ width: "21rem" }}
                  key={category._id}
                >
                  <Card.Header color="#366FF0" className="projectcardheader">
                    {category.categoryName}
                  </Card.Header>
                  <Droppable droppableId={category._id}>
                    {(provided) => (
                      <div
                        className="cardcontent"
                        ref={provided.innerRef}
                        {...provided.droppableProps}
                      >
                        {category.topicIds.map((topicid, index) => {
                          const topic = this.state.Topics[topicid];
                          if (topic) {
                            return (
                              <Draggable draggableId={topic._id} index={index}>
                                {(provided) => (
                                  <Card
                                    onClick={() =>
                                      this.props.handleDiscussionTrue(topic)
                                    }
                                    key={topic._id}
                                    className="topicscard"
                                    {...provided.draggableProps}
                                    {...provided.dragHandleProps}
                                    ref={provided.innerRef}
                                  >
                                    <Card.Title className="topicsheading">
                                      {topic.topicName}
                                    </Card.Title>
                                    <Card.Text className="topicdescription">
                                      {topic.topicDescription}
                                    </Card.Text>
                                    <div>
                                      {topic.topicTags ? (
                                        topic.topicTags.map((k) => {
                                          return (
                                            <Badge
                                              variant="primary"
                                              className="tags"
                                            >
                                              {k}
                                            </Badge>
                                          );
                                        })
                                      ) : (
                                        <Badge variant="primary"></Badge>
                                      )}
                                    </div>
                                  </Card>
                                )}
                              </Draggable>
                            );
                          }
                        })}
                        {provided.placeholder}
                      </div>
                    )}
                  </Droppable>
                  <div
                    className="addnewcard"
                    onClick={() => this.handleShow(category._id)}
                  >
                    <IconContext.Provider
                      value={{
                        style: { verticalAlign: "middle" },
                        className: "reacticon",
                      }}
                    >
                      <FiPlus />
                    </IconContext.Provider>{" "}
                    Add another discussion
                  </div>
                </Card>
              );
            })}
          </div>
        </DragDropContext>
      </div>
    );
  }
Example #24
Source File: Board.js    From Trellis with GNU General Public License v3.0 4 votes vote down vote up
export default function Board() {
  const classes = useStyles()
  /* eslint-disable-next-line */
  var { id, name } = useParams()
  const { loading, currBoard, error } = useSelector((state) => state.boards)
  const { listLoading, lists } = useSelector((state) => state.lists)
  const { cardLoading, cards } = useSelector((state) => state.cards)
  const { activities } = useSelector((state) => state.activities)
  const { isValid, user, token, tokenRequest } = useSelector(
    (state) => state.user,
  )
  const [initialData, setInitialData] = useState({})
  const [initDone, setInitDone] = useState(false)
  const addFlag = useRef(true)
  const [addListFlag, setAddListFlag] = useState(false)
  const [listTitle, setListTitle] = useState('')
  const [color, setColor] = useState('white')
  const [url, setUrl] = useState('')
  const [editable, setEditable] = useState(false)
  const [boardTitle, setBoardTitle] = useState('')
  const dispatch = useDispatch()

  if (!loading && name !== currBoard.name && currBoard.name !== undefined)
    name = currBoard.name
  else if (name === undefined) name = ''

  useEffect(() => {
    if (isValid && !error) {
      if (id.length === 24) {
        dispatch(fetchBoardById(id, token))
        dispatch(fetchListsFromBoard(id, token))
        dispatch(fetchsCardsFromBoard(id, token))
        dispatch(fetchActivitiesFromBoard(id, token))
      }
    }
  }, [dispatch, id, isValid, token, error])

  useEffect(() => {
    if (!_.isEmpty(currBoard)) {
      setColor(currBoard.image.color)
      setUrl(currBoard.image.full)
      setBoardTitle(currBoard.name)
      document.title = `${currBoard.name} | Trellis`
    }
  }, [currBoard])

  useEffect(() => {
    if (!listLoading && !cardLoading) {
      const prevState = { tasks: {}, columns: {}, columnOrder: [] }
      // eslint-disable-next-line no-shadow
      const getTaskIds = (id) => {
        const filteredTasks = _.filter(cards, { listId: id })
        const sortedTasks = _.orderBy(filteredTasks, ['order'], ['asc'])
        const taskIds = []
        sortedTasks.forEach((task) => taskIds.push(task._id))
        return taskIds
      }

      const setContent = () => {
        cards.forEach((card) => (prevState.tasks[card._id] = card))
        const sortedLists = _.orderBy(lists, ['order'], ['asc'])
        sortedLists.forEach((list) => {
          prevState.columns[list._id] = {
            ...list,
            taskIds: getTaskIds(list._id),
          }
          prevState.columnOrder.push(list._id)
        })
      }
      setContent()
      setInitialData({ ...prevState })
      setInitDone(true)
    }
  }, [setInitDone, listLoading, cardLoading, setInitialData, cards, lists])

  const onDragEnd = (result) => {
    // eslint-disable-next-line no-var
    var newOrder
    const { destination, source, draggableId, type } = result
    if (!destination) return
    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    )
      return

    if (type === 'list') {
      const listOrder = initialData.columnOrder
      if (destination.index === 0) {
        newOrder = midString('', initialData.columns[listOrder[0]].order)
      } else if (destination.index === listOrder.length - 1) {
        newOrder = midString(
          initialData.columns[listOrder[destination.index]].order,
          '',
        )
      } else if (destination.index < source.index) {
        newOrder = midString(
          initialData.columns[listOrder[destination.index - 1]].order,
          initialData.columns[listOrder[destination.index]].order,
        )
      } else {
        newOrder = midString(
          initialData.columns[listOrder[destination.index]].order,
          initialData.columns[listOrder[destination.index + 1]].order,
        )
      }
      dispatch(updateListById(draggableId, { order: newOrder }))
      const newListOrder = Array.from(initialData.columnOrder)
      const destinationColumn = initialData.columns[draggableId]
      destinationColumn.order = newOrder
      newListOrder.splice(source.index, 1)
      newListOrder.splice(destination.index, 0, draggableId)
      const newData = {
        ...initialData,
        columnOrder: newListOrder,
        columns: {
          ...initialData.columns,
          draggableId: destinationColumn,
        },
      }
      setInitialData(newData)
      return
    }
    const startList = initialData.columns[source.droppableId]
    const endList = initialData.columns[destination.droppableId]

    if (startList === endList) {
      const column = startList
      if (destination.index === 0)
        newOrder = midString('', initialData.tasks[column.taskIds[0]].order)
      else if (destination.index === column.taskIds.length - 1)
        newOrder = midString(
          initialData.tasks[column.taskIds[destination.index]].order,
          '',
        )
      else if (destination.index < source.index)
        newOrder = midString(
          initialData.tasks[column.taskIds[destination.index - 1]].order,
          initialData.tasks[column.taskIds[destination.index]].order,
        )
      else
        newOrder = midString(
          initialData.tasks[column.taskIds[destination.index]].order,
          initialData.tasks[column.taskIds[destination.index + 1]].order,
        )

      dispatch(updateCardById(draggableId, { order: newOrder }))
      const newTaskIds = Array.from(column.taskIds)
      newTaskIds.splice(source.index, 1)
      newTaskIds.splice(destination.index, 0, draggableId)
      const destinationTask = initialData.tasks[draggableId]
      destinationTask.order = newOrder
      const newColumn = {
        ...column,
        taskIds: newTaskIds,
      }
      const newData = {
        ...initialData,
        columns: {
          ...initialData.columns,
          [newColumn._id]: newColumn,
        },
        tasks: {
          ...initialData.tasks,
          draggableId: destinationTask,
        },
      }
      setInitialData(newData)
      return
    }

    // Move from one list to another
    if (endList.taskIds.length === 0) newOrder = 'n'
    else if (destination.index === 0) {
      newOrder = midString('', initialData.tasks[endList.taskIds[0]].order)
    } else if (destination.index === endList.taskIds.length)
      newOrder = midString(
        initialData.tasks[endList.taskIds[destination.index - 1]].order,
        '',
      )
    else
      newOrder = midString(
        initialData.tasks[endList.taskIds[destination.index - 1]].order,
        initialData.tasks[endList.taskIds[destination.index]].order,
      )
    dispatch(
      updateCardById(draggableId, { order: newOrder, listId: endList._id }),
    )
    const text = `${user.username} moved ${initialData.tasks[draggableId].name} from ${startList.name} to ${endList.name}`
    const recentActivity = activities[activities.length - 1]
    if (
      recentActivity.text ===
        `${user.username} moved ${initialData.tasks[draggableId].name} from ${endList.name} to ${startList.name}` &&
      moment(recentActivity.createdAt).fromNow().includes('second')
    ) {
      dispatch(deleteActivityById(recentActivity._id))
    } else dispatch(createNewActivity({ text, boardId: currBoard._id }, token))

    const startTaskIds = Array.from(startList.taskIds)
    startTaskIds.splice(source.index, 1)
    const newStartList = {
      ...startList,
      taskIds: startTaskIds,
    }
    const destinationTask = initialData.tasks[draggableId]
    destinationTask.order = newOrder
    const endTaskIds = Array.from(endList.taskIds)
    endTaskIds.splice(destination.index, 0, draggableId)
    const newEndList = {
      ...endList,
      taskIds: endTaskIds,
    }
    const newData = {
      ...initialData,
      columns: {
        ...initialData.columns,
        [newStartList._id]: newStartList,
        [newEndList._id]: newEndList,
      },
      tasks: {
        ...initialData.tasks,
        draggableId: destinationTask,
      },
    }
    setInitialData(newData)
  }

  if (id.length < 24) return <h1>Invalid URL</h1>
  const handleChange = (e) => {
    e.preventDefault()
    setListTitle(e.target.value)
  }

  const submitHandler = () => {
    if (listTitle === '') return
    const text = listTitle.trim().replace(/\s+/g, ' ')
    if (text === '') {
      setListTitle(listTitle)
      return
    }
    const totalLists = initialData.columnOrder.length
    const postListReq = {
      name: text,
      boardId: currBoard._id,
      order:
        totalLists === 0
          ? 'n'
          : midString(
              initialData.columns[initialData.columnOrder[totalLists - 1]]
                .order,
              '',
            ),
    }
    dispatch(createNewList(postListReq, token))
    dispatch(
      createNewActivity(
        {
          text: `${user.username} added ${listTitle} to this board`,
          boardId: currBoard._id,
        },
        token,
      ),
    )
    setListTitle('')
  }

  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      submitHandler()
    }
  }

  const closeButtonHandler = () => {
    setAddListFlag(false)
    addFlag.current = true
    setListTitle('')
  }

  const handleAddition = () => {
    setAddListFlag(true)
    addFlag.current = false
  }
  const setBackground = (background) => {
    if (background.thumb) {
      setUrl(background.full)
      setColor('white')
      dispatch(
        updateBoardById(
          currBoard._id,
          {
            image: {
              full: background.full,
              thumb: background.thumb,
              color: 'white',
            },
          },
          token,
        ),
      )
    } else {
      setColor(background)
      setUrl('')
      dispatch(
        updateBoardById(
          currBoard._id,
          {
            image: {
              full: '',
              thumb: '',
              color: background,
            },
          },
          token,
        ),
      )
    }
  }

  return (
    <>
      {isValid || tokenRequest ? (
        <div
          className={classes.root}
          style={{
            backgroundColor: `${color}`,
            backgroundImage: `url(${url})`,
            backgroundSize: 'cover',
            backgroundRepeat: 'no-repeat',
          }}
        >
          <Redirect to={`/b/${id}/${name}`} />
          <Header loggedIn />
          {editable ? (
            <div className={classes.editable}>
              <InputBase
                onChange={(e) => {
                  e.preventDefault()
                  setBoardTitle(e.target.value)
                }}
                fullWidth
                value={boardTitle}
                style={{
                  fontWeight: 'bold',
                  fontFamily: 'sans-serif',
                  fontSize: '20px',
                }}
                autoFocus
                onFocus={(e) => {
                  const val = e.target.value
                  e.target.value = ''
                  e.target.value = val
                }}
                onBlur={() => {
                  setEditable(false)
                  const text = boardTitle.trim().replace(/\s+/g, ' ')
                  if (text === '') {
                    setBoardTitle(currBoard.name)
                    return
                  }
                  dispatch(updateBoardById(id, { name: text }, token))
                  currBoard.name = boardTitle
                }}
              />
            </div>
          ) : (
            <BoardHeader
              title={currBoard.name}
              showEditable={() => setEditable(true)}
            />
          )}
          <DragDropContext onDragEnd={onDragEnd}>
            <Droppable
              droppableId="all-columns"
              direction="horizontal"
              type="list"
            >
              {(provided) => (
                <div
                  className={classes.listContainer}
                  {...provided.droppableProps}
                  ref={provided.innerRef}
                >
                  {initDone &&
                    initialData.columnOrder.map((columnId, index) => {
                      const column = initialData.columns[columnId]
                      const tasks = column.taskIds.map(
                        (taskId) => initialData.tasks[taskId],
                      )
                      return (
                        <List
                          key={column._id}
                          column={column}
                          tasks={tasks}
                          index={index}
                        />
                      )
                    })}
                  <div className={classes.wrapper}>
                    {addFlag.current && (
                      <AddItem
                        handleClick={handleAddition}
                        btnText="Add another list"
                        type="list"
                        icon={<AddIcon />}
                        width="256px"
                        color="white"
                      />
                    )}
                    {addListFlag && (
                      <InputCard
                        value={listTitle}
                        changedHandler={handleChange}
                        itemAdded={submitHandler}
                        closeHandler={closeButtonHandler}
                        keyDownHandler={handleKeyDown}
                        type="list"
                        btnText="Add List"
                        placeholder="Enter list title..."
                        width="230px"
                        marginLeft="1"
                      />
                    )}
                  </div>
                  {provided.placeholder}
                </div>
              )}
            </Droppable>
          </DragDropContext>
          <SideMenu
            setBackground={setBackground}
            board={{ id, color, url, title: boardTitle }}
          />
        </div>
      ) : (
        <NotFound />
      )}
    </>
  )
}
Example #25
Source File: socialform.js    From linkin with MIT License 4 votes vote down vote up
LinksForm = ({ pagedataid }) => {
  const [{ socialLinks }, dispatch] = useStateValue();
  const [loading, setloading] = useState(false);
  const [isNewLinkInList, setisNewLinkInList] = useState(false);

  const addNewLink = () => {
    // console.log(links.length);
    // console.log(links[links.length - 1]);
    setisNewLinkInList(true);

    let newLink = socialLinks[socialLinks.length - 1];

    if (newLink && !newLink.hasOwnProperty("id")) {
      // console.log("new link on arr");
      return;
    }
    dispatch({
      type: "updateSocial",
      socialdata: [
        ...socialLinks,
        {
          linkUrl: "",
          pagedataid: pagedataid,
          bgColor: "#2c6bed",
          active: true,
          borderRadius: "4px",
        },
      ],
    });
  };

  const saveLinkData = async (socialdata) => {
    // console.log("save linkdata");
    // console.log(linkdata);
    setloading(true);

    let operation = "insertlinks";
    if (socialdata.hasOwnProperty("id")) {
      operation = `updatelinks`;
    }

    if (operation === "insertlinks") {
      setisNewLinkInList(false);
    }

    // console.log(operation);
    try {
      let res = await fetch(`${endpoint}/api/social/${operation}`, {
        method: "POST",
        body: JSON.stringify(socialdata),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      // console.log(res);

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        setloading(false);
        return;
      }

      dispatch({ type: "updateSocial", socialdata: res.updatedSocialData });
      toast.success(
        `${
          operation === "insertlinks"
            ? "Added new Social Icon "
            : "Updated Social Icon " + " successfully"
        }`,
        { autoClose: 1000 }
      );
    } catch (error) {
      console.log(error);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
    setloading(false);
  };

  const deleteLink = async (id) => {
    let confirm = await Swal.fire({
      title: "Delete Social Icon",
      text: "You won't be able to revert this!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, delete it!",
    });

    if (!confirm.isConfirmed) {
      return;
    }
    // console.log("delete link");
    // console.log(id);
    setloading(true);

    try {
      let res = await fetch(`${endpoint}/api/social/deletelink`, {
        method: "POST",
        body: JSON.stringify({ id: id }),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      console.log(res);

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        setloading(false);
        return;
      }
      dispatch({ type: "deleteSocial", id: id });
      toast.success(`Successfully deleted Social Icon`, { autoClose: 1000 });
    } catch (error) {
      console.log(error);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
    setloading(false);
  };

  const dragEndHnadler = async (data) => {
    // console.log(data);
    if (!data.destination) {
      return;
    }

    if (data.destination.index === data.source.index) {
      return;
    }

    setloading(true);

    const items = Array.from(socialLinks);
    const [reorderedItem] = items.splice(data.source.index, 1);
    items.splice(data.destination.index, 0, reorderedItem);

    let updateditems = items.map((item, index) => {
      item.orderIndex = index;
      return item;
    });

    dispatch({ type: "updateSocial", socialdata: updateditems });

    let orderData = updateditems.map((item) => {
      return {
        id: item.id,
        name: item.displayText,
        orderIndex: item.orderIndex,
      };
    });

    // console.log(orderData);

    try {
      let res = await fetch(`${endpoint}/api/social/reorderlinks`, {
        method: "POST",
        body: JSON.stringify({ orderData }),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        return;
      }

      toast.success(`Successfully reordered links`, { autoClose: 1000 });
      setloading(false);
    } catch (error) {
      console.log(error);
      setloading(false);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
  };

  return (
    <>
      <div className={styles.Wrapper}>
        <div
          className={`${styles.Inner} col-10 col-sm-10 col-md-10 col-lg-10 col-xl-10 col-xxl-8 `}
        >
          <h3>Social Data</h3>
          {loading && (
            <div className="d-grid gap-2 d-md-flex justify-content-end">
              <span
                className="spinner-border text-info spinner-border me-1"
                role="status"
                aria-hidden="true"
              ></span>
            </div>
          )}
          <button
            type="button"
            className="btn btn-outline-primary"
            onClick={(e) => {
              addNewLink();
            }}
          >
            Add new Social Icon
          </button>
          <DragDropContext onDragEnd={dragEndHnadler}>
            <Droppable droppableId="links" isDropDisabled={isNewLinkInList}>
              {(provided) => (
                <div
                  className="links"
                  {...provided.droppableProps}
                  ref={provided.innerRef}
                >
                  {socialLinks.length > 0 &&
                    socialLinks.map((item, index) => {
                      return (
                        <LinkCard
                          key={index}
                          deleteLink={deleteLink}
                          updateLink={saveLinkData}
                          loading={loading}
                          item={item}
                          index={index}
                          isDragDisabled={isNewLinkInList}
                        />
                      );
                    })}
                  {provided.placeholder}
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </div>
        <ToastContainer
          position="bottom-left"
          hideProgressBar={true}
          newestOnTop={false}
          closeOnClick
          rtl={false}
          pauseOnFocusLoss
          draggable
          pauseOnHover
        />
        <div className="mb-5"></div>
      </div>
    </>
  );
}
Example #26
Source File: linksform.js    From linkin with MIT License 4 votes vote down vote up
LinksForm = ({ pagedataid }) => {
  const [{ links }, dispatch] = useStateValue();
  const [loading, setloading] = useState(false);
  const [commonSettingsCollapse, setcommonSettingsCollapse] = useState(false);
  const [isNewLinkInList, setisNewLinkInList] = useState(false);

  const {
    register,
    handleSubmit,
    formState: { errors, dirtyFields },
  } = useForm();
  const addNewLink = () => {
    // console.log(links.length);
    // console.log(links[links.length - 1]);
    setisNewLinkInList(true);

    let newLink = links[links.length - 1];

    if (newLink && !newLink.hasOwnProperty("id")) {
      // console.log("new link on arr");
      return;
    }
    dispatch({
      type: "updateLink",
      linkdata: [
        ...links,
        {
          linkUrl: "",
          displayText: "",
          pagedataid: pagedataid,
          bgColor: "#2c6bed",
          active: true,
          textColor: "#ffffff",
          borderRadius: "4px",
        },
      ],
    });
  };

  const saveLinkData = async (linkdata) => {
    // console.log("save linkdata");
    // console.log(linkdata);
    setloading(true);

    let operation = "insertlinks";
    if (linkdata.hasOwnProperty("id")) {
      operation = `updatelinks`;
    }

    if (operation === "insertlinks") {
      setisNewLinkInList(false);
    }

    // console.log(operation);
    try {
      let res = await fetch(`${endpoint}/api/pages/${operation}`, {
        method: "POST",
        body: JSON.stringify(linkdata),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      // console.log(res);

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        setloading(false);
        return;
      }

      dispatch({ type: "updateLink", linkdata: res.updatedLinkData });
      toast.success(
        `${
          operation === "insertlinks"
            ? "Added new page link "
            : "Updated page link " + " successfully"
        }`,
        { autoClose: 1000 }
      );
    } catch (error) {
      console.log(error);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
    setloading(false);
  };

  const deleteLink = async (id) => {
    let confirm = await Swal.fire({
      title: "Delete Link",
      text: "You won't be able to revert this!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, delete it!",
    });

    if (!confirm.isConfirmed) {
      return;
    }
    // console.log("delete link");
    // console.log(id);
    setloading(true);

    try {
      let res = await fetch(`${endpoint}/api/pages/deletelink`, {
        method: "POST",
        body: JSON.stringify({ id: id }),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      // console.log(res);

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        setloading(false);
        return;
      }
      dispatch({ type: "deleteLink", id: id });
      toast.success(`Successfully deleted link`, { autoClose: 1000 });
    } catch (error) {
      console.log(error);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
    setloading(false);
  };

  const dragEndHnadler = async (data) => {
    // console.log(data);
    if (!data.destination) {
      return;
    }

    if (data.destination.index === data.source.index) {
      return;
    }

    setloading(true);

    const items = Array.from(links);
    const [reorderedItem] = items.splice(data.source.index, 1);
    items.splice(data.destination.index, 0, reorderedItem);

    let updateditems = items.map((item, index) => {
      item.orderIndex = index;
      return item;
    });

    dispatch({ type: "updateLink", linkdata: updateditems });

    let orderData = updateditems.map((item) => {
      return {
        id: item.id,
        name: item.displayText,
        orderIndex: item.orderIndex,
      };
    });

    // console.log(orderData);

    try {
      let res = await fetch(`${endpoint}/api/pages/reorderlinks`, {
        method: "POST",
        body: JSON.stringify({ orderData }),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        return;
      }

      toast.success(`Successfully reordered links`, { autoClose: 1000 });
      setloading(false);
    } catch (error) {
      console.log(error);
      setloading(false);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
  };

  const updateCommonSettings = async (data) => {
    // console.log(data);
    // console.log(dirtyFields);
    // only get user changed data

    if (Object.keys(dirtyFields).length === 0) {
      return;
    }

    Object.keys(data).forEach((element) => {
      if (!dirtyFields[element]) {
        delete data[element];
      }
    });

    // console.log(data);

    let confirm = await Swal.fire({
      title: "Apply common settings",
      text: "All your links will apply these common settings",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, apply it!",
    });

    if (!confirm.isConfirmed) {
      return;
    }

    setloading(true);

    try {
      let res = await fetch(`${endpoint}/api/pages/applycommonsettigns`, {
        method: "POST",
        body: JSON.stringify(data),
        headers: { "Content-Type": "application/json" },
      }).then((res) => res.json());

      // console.log(res);

      if (!res.success) {
        toast.error(`Error ${res.message}`, { autoClose: 5000 });
        setloading(false);
        return;
      }

      dispatch({ type: "updateLink", linkdata: res.updatedLinkData });

      toast.success(`Successfully applied common settings`, {
        autoClose: 1000,
      });
    } catch (error) {
      console.log(error);
      toast.error(`Error : ${error.message}`, { autoClose: 5000 });
    }
    setloading(false);
  };

  return (
    <>
      <div className={styles.Wrapper}>
        <div
          className={`${styles.Inner} col-10 col-sm-10 col-md-10 col-lg-10 col-xl-10 col-xxl-8 `}
        >
          <h3>Link Data</h3>
          {loading && (
            <div className="d-grid gap-2 d-md-flex justify-content-end">
              <span
                className="spinner-border text-info spinner-border me-1"
                role="status"
                aria-hidden="true"
              ></span>
            </div>
          )}
          <button
            type="button"
            className="btn btn-outline-primary"
            onClick={(e) => {
              addNewLink();
            }}
          >
            Add new link
          </button>
          <div>
            <div className="mt-3 py-2">
              <div className="accordion">
                <div className="accordion-item">
                  <h2 className="accordion-header" id="headingOne">
                    <button
                      className={`accordion-button ${
                        commonSettingsCollapse ? "collapsed" : ""
                      } `}
                      type="button"
                      onClick={(e) => {
                        setcommonSettingsCollapse(!commonSettingsCollapse);
                      }}
                    >
                      Common Settings
                    </button>
                  </h2>{" "}
                  <div
                    className={`accordion-collapse collapse ${
                      commonSettingsCollapse ? "show" : ""
                    }  `}
                  >
                    <div className="accordion-body">
                      <form onSubmit={handleSubmit(updateCommonSettings)}>
                        {" "}
                        <div className="mb-3 ">
                          <div className="input-group mb-3">
                            <input
                              type="number"
                              className={
                                errors.borderRadius
                                  ? "form-control is-invalid"
                                  : "form-control"
                              }
                              placeholder="Enter Border Radius"
                              {...register("borderRadius", {
                                min: {
                                  message: "Border Radius must be above 0px",
                                  value: 0,
                                },
                              })}
                            />
                            <span className="input-group-text">px</span>
                            {errors.borderRadius && (
                              <div className="invalid-feedback">
                                {errors.borderRadius.message}
                              </div>
                            )}
                          </div>
                        </div>
                        <div className="row">
                          <div className="col">
                            <div className="mb-1 small ">
                              <label className="form-label small ">
                                Link Display Text Font color
                              </label>
                              <input
                                type="color"
                                className="form-control form-control-sm mb-2 form-control-color"
                                title="Choose Link text color"
                                placeholder="Choose Link text color"
                                {...register("textColor")}
                              />
                            </div>
                          </div>
                          <div className="col">
                            <div className="mb-1 small ">
                              <label className="form-label small">
                                Link background color
                              </label>
                              <input
                                type="color"
                                className="form-control form-control-sm mb-2 form-control-color"
                                title="Choose Link background color"
                                placeholder="Choose Link background color"
                                {...register("bgColor", { required: "" })}
                              />
                            </div>
                          </div>
                        </div>{" "}
                        <button
                          type="submit"
                          className="btn btn-primary btn-block"
                          disabled={loading}
                        >
                          {loading && (
                            <span
                              className="spinner-border spinner-border-sm me-1"
                              role="status"
                              aria-hidden="true"
                            ></span>
                          )}
                          Save
                        </button>
                      </form>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <DragDropContext onDragEnd={dragEndHnadler}>
            <Droppable droppableId="links" isDropDisabled={isNewLinkInList}>
              {(provided) => (
                <div
                  className="links"
                  {...provided.droppableProps}
                  ref={provided.innerRef}
                >
                  {links.length > 0 &&
                    links.map((item, index) => {
                      return (
                        <LinkCard
                          key={index}
                          deleteLink={deleteLink}
                          updateLink={saveLinkData}
                          loading={loading}
                          item={item}
                          index={index}
                          isDragDisabled={isNewLinkInList}
                        />
                      );
                    })}
                  {provided.placeholder}
                </div>
              )}
            </Droppable>
          </DragDropContext>
        </div>
        <ToastContainer
          position="bottom-left"
          hideProgressBar={true}
          newestOnTop={false}
          closeOnClick
          rtl={false}
          pauseOnFocusLoss
          draggable
          pauseOnHover
        />
        <div className="mb-5"></div>
      </div>
    </>
  );
}
Example #27
Source File: PackAppsList.js    From winstall with GNU General Public License v3.0 4 votes vote down vote up
function PackAppsList({ notLoggedIn = false, providedApps, reorderEnabled, onListUpdate, allApps}){

    const [apps, setApps] = useState([]);
    const [, updateState] = useState();
    const forceUpdate = useCallback(() => updateState({}), []);
    const [showAdd, setShowAdd] = useState(false);

    useEffect(() => {
        setApps(providedApps)
    }, [])
    
    if(!reorderEnabled){
        return (
          <ul className={`${styles.appsList} ${styles.noDragList}`}> 
            {apps.map((app) => (
              <div className={styles.appCard} key={app._id}>
                <SingleApp app={app} pack={true} displaySelect={true}/>
              </div>
            ))}
          </ul>
        );
    }

    const onDragEnd = (result) => {
      if (!result.destination) {
        return;
      }

      if (result.destination.index === result.source.index) {
        return;
      }

      const updatedApps = reorder(
        apps,
        result.source.index,
        result.destination.index
      );


      onListUpdate(updatedApps)

      setApps(updatedApps);
    }

    const manageUpdates = (id) => {
      const updatedApps = apps.filter(i => i._id !== id);
      setApps(updatedApps);
      onListUpdate(updatedApps);
    }

    const handleSelect = (app, isSelected) => {
      let existingApps = apps;

      if (isSelected) {
        existingApps.push(app);
      } else {
        existingApps = existingApps.filter(a => a._id !== app._id);
      }

      setApps(existingApps);
      onListUpdate(existingApps);
      
      forceUpdate();
    }

    const closeModal = () => {
      setShowAdd(false);
    }

    return (
      <>
        <h2>Apps in this pack</h2>
        {!notLoggedIn && <p>Tip! Drag and drop any app to re-order how they appear in your pack.</p>}

        <button className={`button center ${apps.length === 0 ? '' : 'subtle'}`} onClick={() => setShowAdd(!showAdd)}><FiPlusCircle/> {`Add ${apps.length != 0 ? "More" : ""} Apps`}</button><br/>

        <Modal
          isOpen={showAdd}
          onRequestClose={closeModal}
          className={styles.addModal}
          overlayClassName={styles.modalOverlay}
          contentLabel="Example Modal"
        >
          <div className={styles.modalHeader}>
            <h2>Add Apps</h2>
            <FiXCircle onClick={closeModal}/>
          </div>
          <Search apps={allApps} preventGlobalSelect={handleSelect} isPackView={true} alreadySelected={apps} limit={4}/>
        </Modal>
   
        {notLoggedIn ? <p>You need to login first before you can view the apps in this pack.</p> : (
          <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="list">
              {(provided) => (
                <ul
                  ref={provided.innerRef}
                  {...provided.droppableProps}
                  className={styles.appsList}
                >
                  <AppsList apps={apps} onListUpdate={manageUpdates} />
                  {provided.placeholder}
                </ul>
              )}
            </Droppable>
          </DragDropContext>
        ) }
      </>
    );

}
Example #28
Source File: index.js    From website with MIT License 4 votes vote down vote up
DragNDropInputField = ({ onChange, error, initialImages = null }) => {
  const [selectedImages, setSelectedImages] = useState([]);
  const [alertMessage, setAlertMessage] = useState('');
  const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject } = useDropzone({
    onDrop: (files) => onUpload(files, selectedImages),
    accept: '.jpeg, .png, .jpg',
  });

  const onCloseAlert = () => setAlertMessage('');

  const displayUploadFileAlert = (message) => {
    setAlertMessage(message);
    setTimeout(() => {
      onCloseAlert(); // hide alert message after 5 seconds
    }, 5000);
  };

  const onUpload = useCallback((acceptedFiles, selectedImages) => {
    if (acceptedFiles.some((file) => file.size > MAXIMUM_FILE_SIZE_LIMIT)) {
      displayUploadFileAlert('Unable to upload images that are more than 25mb');
      acceptedFiles = acceptedFiles.filter((file) => file.size <= MAXIMUM_FILE_SIZE_LIMIT);
    }

    const allowedRemainingImages = MAXIMUM_ALLOWED_PHOTOS - selectedImages.length;
    if (allowedRemainingImages < acceptedFiles.length) {
      displayUploadFileAlert('Unable to upload more than 4 images');
    }

    // Only take maximum 4 images.
    if (acceptedFiles.length > 0 && selectedImages.length <= MAXIMUM_ALLOWED_PHOTOS - 1) {
      const acceptedImages = acceptedFiles.map((file) => {
        return Object.assign(file, {
          preview: URL.createObjectURL(file),
          id: uuidv4(),
        });
      });

      if (allowedRemainingImages > 0) {
        const allowedImages = acceptedImages.splice(0, allowedRemainingImages);
        setSelectedImages((prevSelectedImages) => [...prevSelectedImages, ...allowedImages]);
      }
    }
  }, []);

  useEffect(() => {
    onChange(selectedImages);
  }, [selectedImages]);

  useEffect(() => {
    if (initialImages) {
      let initial = initialImages.map((imageUrl) => ({
        preview: imageUrl,
        id: uuidv4(),
      }));
      setSelectedImages(initial);
    }
  }, [initialImages]);

  const onDragEnd = (result) => {
    if (!result.destination) {
      // dropped outside the list
      return;
    }
    const items = reorder(selectedImages, result.source.index, result.destination.index);
    setSelectedImages(items);
  };

  // a little function to help us with reordering the result
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  const onDeleteClick = (index) => {
    let cloneSelectedImages = [...selectedImages];
    cloneSelectedImages.splice(index, 1);
    setSelectedImages(cloneSelectedImages);
  };

  return (
    <Container>
      <DragNDropContainer {...getRootProps({ isDragActive, isDragAccept, isDragReject })}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop up to {MAXIMUM_ALLOWED_PHOTOS} photos, or click to select photos</p>
      </DragNDropContainer>
      {error && <Error>{error}</Error>}

      <DragDropContext onDragEnd={onDragEnd}>
        <Droppable droppableId="droppable" direction="horizontal">
          {(provided, snapshot) => (
            <HorizontalImagesContainer ref={provided.innerRef} {...provided.droppableProps}>
              {selectedImages.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index={index}>
                  {(provided, snapshot) => (
                    <DraggableImageContainer
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      isDragging={snapshot.isDragging}
                      draggableStyle={provided.draggableProps.style}
                    >
                      <Image src={item.preview} onDeleteClick={() => onDeleteClick(index)} />
                    </DraggableImageContainer>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </HorizontalImagesContainer>
          )}
        </Droppable>
      </DragDropContext>

      {selectedImages.length > 0 ? (
        <CoverTextWrapper>
          <Text type="white" align="center">
            Cover
          </Text>
        </CoverTextWrapper>
      ) : null}
      {alertMessage.length > 0 && (
        <AlertContainer>
          <Alert icon type="critical" title="Something has gone wrong" closable onClose={onCloseAlert}>
            {alertMessage}
          </Alert>
        </AlertContainer>
      )}
    </Container>
  );
}
Example #29
Source File: index.js    From ActiveLearningStudio-react-client with GNU Affero General Public License v3.0 4 votes vote down vote up
ProjectsPage = (props) => {
  const allStateProject = useSelector((state) => state.project);
  const [show, setShow] = useState(false);
  const [selectedProjectId, setSelectedProjectId] = useState(0);
  const [activeFilter, setActiveFilter] = useState("small-grid");
  const [allProjects, setAllProjects] = useState(null);
  const [value, setValue] = useState(0);
  const [projectDivider, setProjectDivider] = useState([]);
  const [sortNumber, setSortNumber] = useState(5);
  const [customCardWidth, setCustomCardWidth] = useState("customcard20");
  const [sampleProject, setSampleProjects] = useState([]);
  const [favProject, setFavProjects] = useState([]);
  const [teamProjects, setTeamProjects] = useState([]);
  const [activeTab, setActiveTab] = useState("My Projects");
  const [showSampleSort, setShowSampleSort] = useState(true);
  const [activePage, setActivePage] = useState(1);
  const [meta, setMeta] = useState(1);
  const [tabToggle, setTabToggle] = useState([]);
  const [type, setType] = useState([]);
  const [searchTeamQuery, SetSearchTeamQuery] = useState("");
  const [createProject, setCreateProject] = useState(false);
  const [noProjectAlert, setNoProjectAlert] = useState(false);
  const samplerRef = useRef();
  const {
    ui,
    showPreview,
    showDeletePopup,
    loadMyReorderProjectsActionMethod,
    // allSidebarProjectsUpdate,
    sampleProjectsData,
    loadMyFavProjectsActionData,
    location,
    loadMyProjects,
    loadLms,
    getTeamProjects,
  } = props;

  const allState = useSelector((state) => state);
  const { organization } = allState;
  const { permission } = organization;
  useEffect(() => {
    const query = QueryString.parse(location.search);
    if (query.active === "fav") {
      setActiveTab("Favorite Projects");
    } else {
      setActiveTab("My Projects");
    }
  }, []);

  useEffect(() => {
    const sw = window.innerWidth;
    if (sw < 1200) {
      setSortNumber(3);
      setCustomCardWidth("customcard30");
    } else if (sw < 1600) {
      setSortNumber(4);
      setCustomCardWidth("customcard50");
    } else if (sw > 1600) {
      setSortNumber(6);
      setCustomCardWidth("customcard60");
    }
  }, [window.innerWidth]);

  useMemo(() => {
    if (!searchTeamQuery) {
      if (organization?.currentOrganization) {
        getTeamProjects("", activePage).then((data) => {
          setTeamProjects(data.data);
          setMeta(data.meta);
        });
      }
    } else if (searchTeamQuery && organization?.currentOrganization) {
      getTeamProjects(searchTeamQuery, activePage).then((data) => {
        setTeamProjects(data.data);
        setMeta(data.meta);
      });
    }
  }, [getTeamProjects, organization?.currentOrganization, activePage]);
  useEffect(() => {
    if (!searchTeamQuery && organization?.currentOrganization) {
      getTeamProjects("", activePage).then((data) => {
        setTeamProjects(data.data);
        setMeta(data.meta);
      });
    }
  }, [searchTeamQuery]);
  useEffect(() => {
    if (organization?.currentOrganization) {
      sampleProjectsData();
    }
  }, [sampleProjectsData, organization?.currentOrganization]);

  useEffect(() => {
    if (organization?.currentOrganization) {
      loadMyFavProjectsActionData();
    }
  }, [loadMyFavProjectsActionData, organization?.currentOrganization]);

  useEffect(() => {
    // if (allState.sidebar.updateProject.length > 0) {
    setFavProjects(allState.sidebar.updateProject);
    // }
  }, [allState.sidebar.updateProject]);

  useEffect(() => {
    if (allState.sidebar.sampleProject.length > 0) {
      setSampleProjects(allState.sidebar.sampleProject);
    }
  }, [allState.sidebar.sampleProject]);
  const handleSearchQueryTeams = () => {
    getTeamProjects(searchTeamQuery || "", activePage).then((data) => {
      setTeamProjects(data.data);
      setMeta(data.meta);
    });
  };
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  const move = (source, destination, droppableSource, droppableDestination) => {
    const sourceClone = Array.from(source);
    const destClone = Array.from(destination);
    const [removed] = sourceClone.splice(droppableSource.index, 1);

    destClone.splice(droppableDestination.index, 0, removed);

    const result = {};
    result[droppableSource.droppableId] = sourceClone;
    result[droppableDestination.droppableId] = destClone;

    return result;
  };

  let array6 = [];
  const allChunk = [];

  const divideProjects = (dividerProjects) => {
    dividerProjects.forEach((data, counter) => {
      if ((counter + 1) % sortNumber === 0) {
        array6.push(data);
        allChunk.push({
          id: `project_chunk${counter}`,
          collection: array6,
        });
        array6 = [];
      } else if (allStateProject.projects.length === counter + 1) {
        array6.push(data);
        allChunk.push({
          id: `project_chunk${counter}`,
          collection: array6,
        });
        array6 = [];
      } else {
        array6.push(data);
      }
    });

    setProjectDivider(allChunk);
  };

  const onDragEnd = async (result) => {
    const { source, destination, draggableId } = result;
    // dropped outside the list
    if (!destination) {
      return;
    }

    if (source.droppableId === destination.droppableId) {
      projectDivider.forEach(async (data, index) => {
        if (data.id === source.droppableId) {
          const items = reorder(
            data.collection,
            source.index,
            destination.index
          );

          projectDivider[index] = {
            id: data.id,
            collection: items,
          };

          setProjectDivider(projectDivider);
          setValue((v) => v + 1);
          await loadMyReorderProjectsActionMethod(draggableId, projectDivider);
        }
      });
    } else {
      let verticalSource = "";
      let verticalDestination = "";
      projectDivider.forEach((data) => {
        if (data.id === source.droppableId) {
          verticalSource = data.collection;
        }
        if (data.id === destination.droppableId) {
          verticalDestination = data.collection;
        }
      });

      const res = move(
        verticalSource,
        verticalDestination,
        source,
        destination
      );

      Object.keys(res).forEach((key) => {
        projectDivider.forEach((data, index) => {
          if (data.id === key) {
            projectDivider[index] = {
              id: data.id,
              collection: res[key],
            };
          }
        });
      });

      const updateProjectList = [];
      projectDivider.forEach((data) =>
        data.collection.forEach((arrays) => {
          updateProjectList.push(arrays);
        })
      );

      setProjectDivider(projectDivider);
      divideProjects(updateProjectList);
      await loadMyReorderProjectsActionMethod(draggableId, projectDivider);
    }
  };

  useEffect(() => {
    if (allStateProject.projects.length > 0) {
      setNoProjectAlert(false);
      toast.dismiss();
    } else if (allProjects?.length === 0) {
      setNoProjectAlert(true);
    }
    setAllProjects(allStateProject.projects);
    divideProjects(allStateProject.projects);
    // }
  }, [allStateProject]);

  // useEffect(() => {
  //   const { activeOrganization } = organization;
  //   if (activeOrganization) {
  //     allSidebarProjectsUpdate();
  //   }
  // }, [organization.activeOrganization]);

  useEffect(() => {
    loadLms();
  }, []);
  useMemo(() => {
    // scroll to top
    window.scrollTo(0, 0);
    document.body.classList.remove("mobile-responsive");

    if (organization.activeOrganization && !allState.projects) {
      toast.info("Loading Projects ...", {
        className: "project-loading",
        closeOnClick: false,
        closeButton: false,
        position: toast.POSITION.BOTTOM_RIGHT,
        autoClose: 10000,
        icon: ImgLoader,
      });
      if (organization?.currentOrganization) {
        loadMyProjects();
      }
    }
  }, [organization?.currentOrganization]);

  useEffect(() => {
    if (allProjects) {
      divideProjects(allProjects);
    }
  }, [allProjects, sortNumber]);

  const handleShow = () => {
    setShow(true); //! state.show
  };

  const setProjectId = (projectId) => {
    setSelectedProjectId(projectId);
  };

  const handleClose = () => {
    setShow(false);
  };

  const handleDeleteProject = (projectId) => {
    const { deleteProject } = props;
    if (window.confirm("Are you Sure?")) {
      deleteProject(projectId);
    }
  };

  const handleShareProject = (projectId) => {
    const { shareProject } = props;
    shareProject(projectId);
  };

  // const handleTabChange = (key) => {
  //   if (key === 'Favorite Projects') {
  //     setTabToggle(true);
  //   } else if (key === 'Sample Projects') {
  //     setTabToggle(false);
  //   }
  // };

  const { showDeletePlaylistPopup } = ui;

  return (
    <>
      <div className={`content-wrapper ${activeFilter}`}>
        <div className={`inner-content  ${customCardWidth}`}>
          <div className="">
            <Headline setCreateProject={setCreateProject} />
            {permission?.Project?.includes("project:view") ? (
              <Tabs
                onSelect={(eventKey) => {
                  setShowSampleSort(true);
                  setTabToggle(eventKey);
                  if (eventKey === "Sample Projects") {
                    setType("sample");
                  } else if (eventKey === "Favorite Projects") {
                    setType("fav");
                  } else if (eventKey === "Team Projects") {
                    setType("team");
                  }
                }}
                className="main-tabs"
                defaultActiveKey={activeTab}
                id="uncontrolled-tab-example"
              >
                <Tab eventKey="My Projects" title="My Projects">
                  <div className="row">
                    <div className="col-md-12">
                      {!!projectDivider && projectDivider.length > 0 ? (
                        <>
                          <div className="project-list-all">
                            <DragDropContext onDragEnd={onDragEnd}>
                              {projectDivider.map((rowData) => (
                                <Droppable
                                  key={rowData.id}
                                  droppableId={rowData.id}
                                  // direction="horizontal"
                                  // type="row"
                                  className="drag-class"
                                  direction="horizontal"
                                >
                                  {(provided) => (
                                    <div
                                      {...provided.droppableProps}
                                      ref={provided.innerRef}
                                    >
                                      <div className="check-home" id={value}>
                                        {/* <div id={value}> */}
                                        {rowData.collection.map(
                                          (proj, index) => {
                                            const res = {
                                              title: proj.name,
                                              id: proj.id,
                                              deleteType: "Project",
                                            };
                                            return (
                                              <Draggable
                                                key={proj.id}
                                                draggableId={`${proj.id}`}
                                                index={index}
                                              >
                                                {(provid) => (
                                                  <div
                                                    className="playlist-resource"
                                                    ref={provid.innerRef}
                                                    {...provid.draggableProps}
                                                    {...provid.dragHandleProps}
                                                  >
                                                    <ProjectCard
                                                      key={proj.id}
                                                      project={proj}
                                                      res={res}
                                                      handleDeleteProject={
                                                        handleDeleteProject
                                                      }
                                                      handleShareProject={
                                                        handleShareProject
                                                      }
                                                      showDeletePopup={
                                                        showDeletePopup
                                                      }
                                                      showPreview={
                                                        showPreview === proj.id
                                                      }
                                                      handleShow={handleShow}
                                                      handleClose={handleClose}
                                                      setProjectId={
                                                        setProjectId
                                                      }
                                                      activeFilter={
                                                        activeFilter
                                                      }
                                                      setCreateProject={
                                                        setCreateProject
                                                      }
                                                    />
                                                  </div>
                                                )}
                                              </Draggable>
                                            );
                                          }
                                        )}
                                      </div>
                                      {provided.placeholder}
                                    </div>
                                  )}
                                </Droppable>
                              ))}
                            </DragDropContext>
                          </div>
                        </>
                      ) : (
                        <Initialpage />
                      )}
                    </div>
                  </div>
                </Tab>
                {permission?.Project?.includes("project:favorite") && (
                  <Tab eventKey="Favorite Projects" title="Favorite Projects">
                    <div className="row">
                      <div className="col-md-12" style={{ display: "none" }}>
                        <div className="program-page-title">
                          <h1>Favorite Projects</h1>
                          {showSampleSort && favProject.length === 0 && (
                            <div className="project-page-settings">
                              <div className="sort-project-btns">
                                <div
                                  className={
                                    activeFilter === "list-grid"
                                      ? "sort-btn active"
                                      : "sort-btn"
                                  }
                                  onClick={() => {
                                    // const allchunk = [];
                                    // var counterSimpl = 0;
                                    setActiveFilter("list-grid");
                                    setSortNumber(-1);
                                    divideProjects(allProjects);
                                  }}
                                >
                                  <FontAwesomeIcon icon="bars" />
                                </div>
                                <div
                                  className={
                                    activeFilter === "small-grid"
                                      ? "sort-btn active"
                                      : "sort-btn"
                                  }
                                  onClick={() => {
                                    setActiveFilter("small-grid");
                                    setSortNumber(5);
                                    divideProjects(allProjects);
                                  }}
                                >
                                  <FontAwesomeIcon icon="grip-horizontal" />
                                </div>
                                <div
                                  className={
                                    activeFilter === "normal-grid"
                                      ? "sort-btn active"
                                      : "sort-btn"
                                  }
                                  onClick={() => {
                                    setActiveFilter("normal-grid");
                                    setSortNumber(4);
                                    divideProjects(allProjects);
                                  }}
                                >
                                  <FontAwesomeIcon icon="th-large" />
                                </div>
                              </div>
                            </div>
                          )}
                        </div>
                      </div>

                      <div className="col-md-12">
                        <div className="flex-smaple">
                          {favProject.length > 0 ? (
                            <SampleProjectCard
                              projects={favProject}
                              type={type}
                              activeTab={tabToggle}
                              setType={setType}
                              setTabToggle={setTabToggle}
                              setShowSampleSort={setShowSampleSort}
                            />
                          ) : (
                            <Alert variant="warning">
                              No Favorite Project found.
                            </Alert>
                          )}
                        </div>
                      </div>
                    </div>
                  </Tab>
                )}
                <Tab
                  eventKey="Sample Projects"
                  ref={samplerRef}
                  title="Sample Projects"
                >
                  <div className="row">
                    <div className="col-md-12" style={{ display: "none" }}>
                      <div className="program-page-title">
                        <h1>Sample Projects</h1>

                        {showSampleSort && sampleProject.length === 0 && (
                          <div className="project-page-settings">
                            <div className="sort-project-btns">
                              <div
                                className={
                                  activeFilter === "list-grid"
                                    ? "sort-btn active"
                                    : "sort-btn"
                                }
                                onClick={() => {
                                  // const allchunk = [];
                                  // let counterSimpl = 0;
                                  setActiveFilter("list-grid");
                                  setSortNumber(-1);
                                  divideProjects(allProjects);
                                }}
                              >
                                <FontAwesomeIcon icon="bars" />
                              </div>
                              <div
                                className={
                                  activeFilter === "small-grid"
                                    ? "sort-btn active"
                                    : "sort-btn"
                                }
                                onClick={() => {
                                  setActiveFilter("small-grid");
                                  setSortNumber(5);
                                  divideProjects(allProjects);
                                }}
                              >
                                <FontAwesomeIcon icon="grip-horizontal" />
                              </div>
                              <div
                                className={
                                  activeFilter === "normal-grid"
                                    ? "sort-btn active"
                                    : "sort-btn"
                                }
                                onClick={() => {
                                  setActiveFilter("normal-grid");
                                  setSortNumber(4);
                                  divideProjects(allProjects);
                                }}
                              >
                                <FontAwesomeIcon icon="th-large" />
                              </div>
                            </div>
                          </div>
                        )}
                      </div>
                    </div>

                    <div className="col-md-12">
                      <div className="flex-smaple">
                        {sampleProject.length > 0 ? (
                          <SampleProjectCard
                            projects={sampleProject}
                            activeTab={tabToggle}
                            setType={setType}
                            setTabToggle={setTabToggle}
                            type={type}
                            setShowSampleSort={setShowSampleSort}
                          />
                        ) : (
                          <Alert variant="warning">
                            {" "}
                            No sample project found.
                          </Alert>
                        )}
                      </div>
                    </div>
                  </div>
                </Tab>
                <Tab eventKey="Team Projects" title="Team Projects">
                  <div className="row">
                    <div className="col-md-12" style={{ display: "none" }}>
                      <div className="program-page-title">
                        <h1>Team Projects</h1>
                      </div>
                    </div>
                    <div className="col-md-12">
                      {showSampleSort && (
                        <div className="search-bar-team-tab">
                          <input
                            type="text"
                            placeholder="Search team projects"
                            value={searchTeamQuery}
                            onChange={({ target }) =>
                              SetSearchTeamQuery(target.value)
                            }
                          />
                          <img
                            src={searchimg}
                            alt="search"
                            onClick={handleSearchQueryTeams}
                          />
                        </div>
                      )}
                      <div className="flex-smaple">
                        {teamProjects.length > 0 ? (
                          <SampleProjectCard
                            projects={teamProjects}
                            type={type}
                            setType={setType}
                            setTabToggle={setTabToggle}
                            activeTab={tabToggle}
                            setShowSampleSort={setShowSampleSort}
                            handleShow={handleShow}
                            handleClose={handleClose}
                            setProjectId={setProjectId}
                          />
                        ) : (
                          <Alert variant="warning">
                            No Team Project found.
                          </Alert>
                        )}
                      </div>
                    </div>
                  </div>

                  <div className="pagination-top-team">
                    <div className="pagination_state">
                      {showSampleSort && teamProjects.length > 0 && (
                        <Pagination
                          activePage={activePage}
                          pageRangeDisplayed={5}
                          itemsCountPerPage={Number(meta?.per_page)}
                          totalItemsCount={Number(meta?.total)}
                          onChange={(e) => {
                            // setCurrentTab("index");
                            window.scrollTo(0, 0);
                            setActivePage(e);
                          }}
                        />
                      )}
                    </div>
                  </div>
                </Tab>
              </Tabs>
            ) : (
              <Alert variant="danger">
                {" "}
                You are not authorized to view Projects
              </Alert>
            )}
          </div>
        </div>
      </div>
      {createProject && (
        <NewProjectPage
          project={props?.project}
          handleCloseProjectModal={setCreateProject}
        />
      )}

      {showDeletePlaylistPopup && (
        <DeletePopup {...props} deleteType="Project" />
      )}

      <GoogleModel
        projectId={selectedProjectId}
        show={show} // {props.show}
        onHide={handleClose}
      />
    </>
  );
}