145 lines
3.9 KiB
TypeScript
145 lines
3.9 KiB
TypeScript
import { select, put } from 'redux-saga/effects';
|
|
import { fetchIssues, addLabel, removeLabel } from '../actions/issues';
|
|
import { fetchIssuesSaga } from './issues';
|
|
import { BUILD_KANBOARD_SUCCESS, buildKanboard, BUILD_KANBOARD_FAILURE } from '../actions/kanboards';
|
|
import { Project, Issue } from '../../types/gitea';
|
|
import { Board, BoardLane } from '../../types/board';
|
|
import { KanboardLane, Kanboard, KanboardCard } from '../../types/kanboard';
|
|
|
|
export function* moveCardSaga(action: any) {
|
|
const {
|
|
boardID, fromLaneID,
|
|
fromPosition, toLaneID,
|
|
toPosition,
|
|
} = action;
|
|
|
|
if (fromLaneID === toLaneID) return;
|
|
|
|
const { board, kanboard} = yield select(state => {
|
|
return {
|
|
kanboard: state.kanboards.byID[boardID],
|
|
board: state.boards.byID[boardID]
|
|
}
|
|
});
|
|
|
|
const toLane = kanboard.lanes[toLaneID];
|
|
const card = toLane.cards[toPosition];
|
|
|
|
if (!card) return;
|
|
|
|
yield put(addLabel(card.project, card.issue.number, board.lanes[toLaneID].issueLabel));
|
|
yield put(removeLabel(card.project, card.issue.number, board.lanes[fromLaneID].issueLabel));
|
|
|
|
}
|
|
|
|
export function* buildKanboardSaga(action: any) {
|
|
const { board } = action;
|
|
|
|
let kanboard;
|
|
try {
|
|
|
|
for (let p, i = 0; (p = board.projects[i]); i++) {
|
|
const { project } = yield fetchIssues(p);
|
|
yield fetchIssuesSaga({ project });
|
|
}
|
|
|
|
const issues = yield select(state => state.issues);
|
|
|
|
kanboard = createKanboard(board, issues);
|
|
|
|
} catch(error) {
|
|
yield put({ type: BUILD_KANBOARD_FAILURE, error });
|
|
return
|
|
}
|
|
|
|
yield put({ type: BUILD_KANBOARD_SUCCESS, kanboard });
|
|
}
|
|
|
|
export function* refreshKanboardSaga(action: any) {
|
|
const { project } = action;
|
|
const boards = yield select(state => state.boards);
|
|
const boardValues = Object.values(boards.byID);
|
|
|
|
for (let b: any, i = 0; (b = boardValues[i]); i++) {
|
|
const hasProject = b.projects.indexOf(project) !== -1;
|
|
if (!hasProject) continue;
|
|
yield put(buildKanboard(b));
|
|
}
|
|
}
|
|
|
|
function createCards(projects: Project[], issues: any, lane: BoardLane, rest: Set<KanboardCard>) {
|
|
const cards: KanboardCard[] = projects.reduce((laneCards, p) => {
|
|
|
|
const projectIssues = p in issues.byProject ? issues.byProject[p] : [];
|
|
|
|
return projectIssues.reduce((projectCards: KanboardCard[], issue: any) => {
|
|
|
|
const hasLabel = issue.labels.some((l: any) => l.name === lane.issueLabel);
|
|
const card = getMemoizedKanboardCard(issue.id, issue.title, p, issue);
|
|
|
|
if (hasLabel) {
|
|
projectCards.push(card);
|
|
rest.delete(card);
|
|
} else {
|
|
rest.add(card);
|
|
}
|
|
|
|
return projectCards;
|
|
|
|
}, laneCards);
|
|
|
|
}, []);
|
|
|
|
return cards;
|
|
}
|
|
|
|
const kanboardCardMemo: {[key: string]: KanboardCard} = {};
|
|
|
|
function getMemoizedKanboardCard(id: number, title: string, project: Project, issue: Issue): KanboardCard {
|
|
const key = `${project.id}-${issue.id}-${id}`;
|
|
if (kanboardCardMemo.hasOwnProperty(key)) return kanboardCardMemo[key];
|
|
kanboardCardMemo[key] = { id, title, project, issue };
|
|
return kanboardCardMemo[key];
|
|
}
|
|
|
|
function resetKandboarCardMemo() {
|
|
Object.keys(kanboardCardMemo).forEach(k => delete kanboardCardMemo[k]);
|
|
}
|
|
|
|
function createKanboardLanes(board: Board, issues: any): KanboardLane[] {
|
|
const lanes: KanboardLane[] = [];
|
|
const rest = new Set<KanboardCard>();
|
|
|
|
resetKandboarCardMemo();
|
|
|
|
board.lanes.forEach((l: BoardLane, i: number) => {
|
|
const cards = createCards(board.projects, issues, l, rest);
|
|
lanes.push({
|
|
id: i,
|
|
title: l.title,
|
|
cards,
|
|
});
|
|
});
|
|
|
|
// Assign remaining issues
|
|
board.lanes.forEach((l: BoardLane, i: number) => {
|
|
if (!l.collectRemainingIssues) return;
|
|
lanes[i].cards.push(...Array.from(rest.values()));
|
|
});
|
|
|
|
resetKandboarCardMemo();
|
|
|
|
return lanes;
|
|
}
|
|
|
|
function createKanboard(board: Board, issues: any) {
|
|
if (!board) return null;
|
|
|
|
const kanboard = {
|
|
id: board.id,
|
|
lanes: createKanboardLanes(board, issues),
|
|
};
|
|
|
|
return kanboard;
|
|
}
|