본문 바로가기

IT/mendix

Mendix Widget 만들기 - 칸반보드

반응형

이번에는 위젯으로 칸반보드를 만드는 방법 입니다. 

https://medium.com/@joe.robertson_mx/build-widgets-in-mendix-with-react-part-3-kanban-2598aa71444d

 

Build Widgets in Mendix with React Part 3 — Kanban

Mendix is the number one low code platform, which allows makers to develop applications considerably faster than traditional coding.

medium.com

 

1. 템플릿 작성

yo @mendix/widget kanban

 

옵션은 기본으로 하되, TypeScript  로 합니다!

 

2. Kanban.xml 파일 수정

        <propertyGroup caption="General">
            <property key="items" type="datasource" isList="true" required="true">
                <caption>Items</caption>
                <description>List of items</description>
            </property>
            <property key="widgetList" type="widgets" required="true" dataSource="items">
                <caption>Content</caption>
                <description>Widgets using data source</description>
            </property>
        </propertyGroup>

 

3. 필요없는 파일 삭제 후 임시 빌드

src/components/Alert.tsx

src/components/BadgeSample.tsx

src/Kanban.editorPreview.tsx

 

npm run build

 

typings/KanbanProps.d.ts 에 위젯 입력으로 추가한 items, widgetList 자동 추가됨

 

4. 테스트용 멘딕스 프로젝트 생성

./tests/testProject 에 멘딕스 프로젝트 생성

프로젝트 오픈후 F4(디렉토리싱크) 후 , Kanban 위젯 확인

 

5. 도메인 생성

Entity name : Item

Attribute : Content(String)

 

6. 마이크로플로우 생성 및 프로그램 시작시 기동하도록 설정

 

7. 화면구성

Home 화면에 위젯을 추가하고, 데이터소스로 연결

빌딩블록의 Card 를 이용해서 표시 추가

 

8. 테스트 실행 확인

 

9. 드래그 & 드랍 패키지 추가

npm i react-beautiful-dnd
npm i @types/react-beautiful-dnd

 

typescript 를 쓸때는 @types/패키지 를 추가 안해주면 오류남!;;

 

10. Kanban.tsx 수정

import { ReactElement, createElement } from "react";

import { KanbanContainerProps } from "../typings/KanbanProps";
import "./ui/Kanban.css";

import { Draggable, DragDropContext, DropResult, Droppable } from "react-beautiful-dnd";

export function Kanban({ widgetList, items }: KanbanContainerProps): ReactElement {
    const ItemList = (): ReactElement => {
        return (
            <div>
                {items.items &&
                    items.items.map((item, i) => {
                        return (
                            <Draggable draggableId={item.id} index={i} key={item.id}>
                                {provided => (
                                    <div
                                        ref={provided.innerRef}
                                        {...provided.draggableProps}
                                        {...provided.dragHandleProps}
                                    >
                                        {widgetList.get(item)}
                                    </div>
                                )}
                            </Draggable>
                        );
                    })}
            </div>
        );
    };

    function onDragEnd(result: DropResult): void {
        console.log(result);
        console.log("Dragged");
    }

    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="list">
                {provided => (
                    <div ref={provided.innerRef} {...provided.droppableProps}>
                        <ItemList />
                    </div>
                )}
            </Droppable>
        </DragDropContext>
    );
}

npm run build 후, 멘딕스 스튜디오 프로에서 F4 싱크하여 확인!

 

12. 칸반보드는 여러개의 보드를 가져야 하므로, 여러개의 보드를 선언할 수 있도록 프로퍼티를 변경

            <property key="myObject" type="object" isList="true">
                <caption>Sections</caption>
                <description />
                <properties>
                    <propertyGroup caption="Object list group">
                        <property key="sectionName" type="string" required="true">
                            <caption>Name</caption>
                            <description>Name</description>
                        </property>
                        <property key="sectionItems" type="datasource" isList="true" required="true">
                            <caption>Section Items</caption>
                            <description>List of items</description>
                        </property>
                        <property key="widgetList" type="widgets" required="true" dataSource="sectionItems">
                            <caption>Content</caption>
                            <description>Widgets using data source</description>
                        </property>
                    </propertyGroup>
                </properties>
            </property>

 

13. 위의 수정을 임시로 확인하기 위해 Kanban.tsx 의 일부만 수정하여 확인

import { ReactElement, createElement } from "react";

import { KanbanContainerProps } from "../typings/KanbanProps";
import "./ui/Kanban.css";

import { Draggable, DragDropContext, DropResult, Droppable } from "react-beautiful-dnd";

// 임시:프롭 변경!!
export function Kanban({ myObject }: KanbanContainerProps): ReactElement {
    // 임시:변수 할당!
    const items = myObject[0].sectionItems;
    const widgetList = myObject[0].widgetList;

    const ItemList = (): ReactElement => {
        return (
            <div>
                {items.items &&
                    items.items.map((item, i) => {
                        return (
                            <Draggable draggableId={item.id} index={i} key={item.id}>
                                {provided => (
                                    <div
                                        ref={provided.innerRef}
                                        {...provided.draggableProps}
                                        {...provided.dragHandleProps}
                                    >
                                        {widgetList.get(item)}
                                    </div>
                                )}
                            </Draggable>
                        );
                    })}
            </div>
        );
    };

    function onDragEnd(result: DropResult): void {
        console.log(result);
        console.log("Dragged");
    }

    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="list">
                {provided => (
                    <div ref={provided.innerRef} {...provided.droppableProps}>
                        <ItemList />
                    </div>
                )}
            </Droppable>
        </DragDropContext>
    );
}

 

14. 멘딕스 프로에서 입력 방법 변경 확인

이제 리스트 형태로 데이터소스 여러개를 집어 넣을 수가 있다!!

 

15. 위와 같은 형태로 쓸수 있게 소스 수정. Component 형태로 드래그가 가능하도록 수정해서 동작하게 한다!

src/components/Draggable.tsx

import { ReactElement, createElement } from "react";
import { ObjectItem, ListWidgetValue } from "mendix";
import { Draggable } from "react-beautiful-dnd";

export interface DraggableProps {
    item: ObjectItem;
    i: number;
    widgetList: ListWidgetValue;
}

export function DraggableItem({ item, i, widgetList }: DraggableProps): ReactElement {
    return (
        <Draggable draggableId={item.id} index={i} key={item.id}>
            {provided => (
                <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
                    {widgetList.get(item)}
                </div>
            )}
        </Draggable>
    );
}

src/components/ItemList.tsx

import { ReactElement, createElement } from "react";
import { ListValue, ListWidgetValue } from "mendix";
import { DraggableItem } from "./Draggable";

export interface ItemListProps {
    items: ListValue;
    widgetList: ListWidgetValue;
}
export const ItemList = ({ items, widgetList }: ItemListProps): ReactElement => {
    return (
        items && (
            <div>
                {items.items &&
                    items.items.map((item, i) => {
                        return <DraggableItem item={item} key={i} i={i} widgetList={widgetList} />;
                    })}
            </div>
        )
    );
};

src/Kanban.tsx

import { ReactElement, createElement } from "react";

import { KanbanContainerProps } from "../typings/KanbanProps";
import "./ui/Kanban.css";

import { DragDropContext, DropResult, Droppable } from "react-beautiful-dnd";
import { ItemList } from "./components/ItemList";

export function Kanban({ myObject }: KanbanContainerProps): ReactElement {
    function onDragEnd(result: DropResult): void {
        console.log(result);
        console.log("dragged");
    }
    return (
        <div style={{ display: "flex" }}>
            <DragDropContext onDragEnd={onDragEnd}>
                {myObject.map((obj, i) => {
                    return (
                        <Droppable key={i} droppableId={i.toString()}>
                            {provided => (
                                <div
                                    className="kanban-col"
                                    style={{ width: `${100 / myObject.length}%` }}
                                    ref={provided.innerRef}
                                    {...provided.droppableProps}
                                >
                                    <h6>{obj.sectionName}</h6>
                                    <ItemList items={obj.sectionItems} widgetList={obj.widgetList} />
                                    {provided.placeholder}
                                </div>
                            )}
                        </Droppable>
                    );
                })}
            </DragDropContext>
        </div>
    );
}

src/ui/Kanban.css

.widget-kanban-clickable {
    cursor: pointer;
}

.widget-kanban {
    display: inline-block;
}

.widget-kanban.badge:empty {
    display: initial;
    /* Fix padding to stay round */
    padding: 3px 10px;
}

.widget-kanban.label:empty {
    display: initial;
    /* Fix padding to stay square */
    padding: 0.2em 0.8em 0.3em;
}

.widget-kanban.badge {
    min-width: 18px;
    min-height: 18px;
}

.kanban-col {
    margin: 15px;
    padding: 10px;
    background: #9bedff;
    border-radius: 15px;
}
.kanban-col h6 {
    text-align: center;
}

 

조금의 이쁨? 을 위해 css 코드 수정 추가

 

==  현재까지 진행사항

하지만 드래그 해서  옮겼을경우 반영이 안된다.. 수정필요!

반응형