Base générale d'UI
This commit is contained in:
31
client/src/store/sagas/boards.js
Normal file
31
client/src/store/sagas/boards.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { put, call } from 'redux-saga/effects';
|
||||
import { FETCH_BOARDS_SUCCESS, SAVE_BOARD_SUCCESS, SAVE_BOARD_FAILURE, FETCH_BOARDS_FAILURE } from '../actions/boards';
|
||||
import { api } from '../../util/api';
|
||||
|
||||
const boardsLocalStorageKey = 'giteakan.boards';
|
||||
|
||||
export function* fetchBoardsSaga() {
|
||||
let boards;
|
||||
|
||||
try {
|
||||
boards = yield call(api.fetchBoards)
|
||||
} catch(error) {
|
||||
yield put({ type: FETCH_BOARDS_FAILURE, error });
|
||||
return
|
||||
}
|
||||
|
||||
yield put({ type: FETCH_BOARDS_SUCCESS, boards });
|
||||
}
|
||||
|
||||
export function* saveBoardSaga(action) {
|
||||
let { board } = action;
|
||||
|
||||
try {
|
||||
board = yield call(api.saveBoard, board)
|
||||
} catch(error) {
|
||||
yield put({ type: SAVE_BOARD_FAILURE, error });
|
||||
return
|
||||
}
|
||||
|
||||
yield put({ type: SAVE_BOARD_SUCCESS, board });
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
import { GiteaUnauthorizedError } from "../../util/gitea";
|
||||
import { LOGOUT } from "../actions/logout";
|
||||
import { put } from 'redux-saga/effects';
|
||||
|
||||
export function* handleFailedActionSaga(action) {
|
||||
console.error(action.error);
|
||||
export function* failuresSaga(action) {
|
||||
const err = action.error;
|
||||
if (err instanceof GiteaUnauthorizedError) {
|
||||
yield put({ type: LOGOUT });
|
||||
}
|
||||
}
|
||||
|
59
client/src/store/sagas/issues.js
Normal file
59
client/src/store/sagas/issues.js
Normal file
@ -0,0 +1,59 @@
|
||||
import { put, call, retry } from 'redux-saga/effects';
|
||||
import { FETCH_ISSUES_SUCCESS, FETCH_ISSUES_FAILURE, ADD_LABEL_FAILURE, ADD_LABEL_SUCCESS, REMOVE_LABEL_FAILURE, REMOVE_LABEL_SUCCESS } from '../actions/issues';
|
||||
import { gitea } from '../../util/gitea';
|
||||
|
||||
export function* fetchIssuesSaga(action) {
|
||||
const { project } = action;
|
||||
|
||||
let issues;
|
||||
try {
|
||||
issues = yield call(gitea.fetchIssues.bind(gitea), action.project);
|
||||
} catch(error) {
|
||||
yield put({ type: FETCH_ISSUES_FAILURE, project, error });
|
||||
return;
|
||||
}
|
||||
|
||||
yield put({ type: FETCH_ISSUES_SUCCESS, project, issues });
|
||||
}
|
||||
|
||||
export function* addLabelSaga(action) {
|
||||
const { project, issueNumber, label } = action;
|
||||
const labels = yield call(gitea.fetchProjectLabels.bind(gitea), project);
|
||||
const giteaLabel = labels.find(l => l.name === label)
|
||||
|
||||
if (!giteaLabel) {
|
||||
yield put({ type: ADD_LABEL_FAILURE, error: new Error(`Label "${label}" not found !`) });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
yield retry(5, 250, gitea.addIssueLabel.bind(gitea), project, issueNumber, giteaLabel.id);
|
||||
} catch(error) {
|
||||
yield put({ type: ADD_LABEL_FAILURE, error });
|
||||
return;
|
||||
}
|
||||
|
||||
yield put({ type: ADD_LABEL_SUCCESS, project, issueNumber, label });
|
||||
}
|
||||
|
||||
export function* removeLabelSaga(action) {
|
||||
const { project, issueNumber, label } = action;
|
||||
const labels = yield call(gitea.fetchProjectLabels.bind(gitea), project);
|
||||
const giteaLabel = labels.find(l => l.name === label)
|
||||
|
||||
if (!giteaLabel) {
|
||||
yield put({ type: REMOVE_LABEL_FAILURE, error: new Error(`Label "${label}" not found !`) });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
yield retry(5, 250, gitea.removeIssueLabel.bind(gitea), project, issueNumber, giteaLabel.id);
|
||||
} catch(error) {
|
||||
yield put({ type: REMOVE_LABEL_FAILURE, error });
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
yield put({ type: REMOVE_LABEL_SUCCESS, project, issueNumber, label });
|
||||
|
||||
}
|
98
client/src/store/sagas/kanboards.js
Normal file
98
client/src/store/sagas/kanboards.js
Normal file
@ -0,0 +1,98 @@
|
||||
import { select, put } from 'redux-saga/effects';
|
||||
import { fetchIssues, addLabel, removeLabel } from '../actions/issues';
|
||||
import { fetchIssuesSaga } from './issues';
|
||||
import { BUILD_KANBOARD_SUCCESS } from '../actions/kanboards';
|
||||
|
||||
export function* moveCardSaga(action) {
|
||||
const {
|
||||
boardID, fromLaneID,
|
||||
fromPosition, toLaneID,
|
||||
toPosition,
|
||||
} = action;
|
||||
|
||||
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.number, board.lanes[toLaneID].issueLabel));
|
||||
yield put(removeLabel(card.project, card.number, board.lanes[fromLaneID].issueLabel));
|
||||
|
||||
}
|
||||
|
||||
export function* buildKanboardSaga(action) {
|
||||
|
||||
const { board } = action;
|
||||
|
||||
let kanboard;
|
||||
try {
|
||||
|
||||
for (let p, i = 0; (p = board.projects[i]); i++) {
|
||||
yield* fetchIssuesSaga(fetchIssues(p));
|
||||
}
|
||||
|
||||
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 });
|
||||
|
||||
}
|
||||
|
||||
function createCards(projects, issues, lane) {
|
||||
return projects.reduce((laneCards, p) => {
|
||||
|
||||
const projectIssues = p in issues.byProject ? issues.byProject[p] : [];
|
||||
|
||||
return projectIssues.reduce((projectCards, issue) => {
|
||||
const hasLabel = issue.labels.some(l => l.name === lane.issueLabel);
|
||||
|
||||
if (hasLabel) {
|
||||
projectCards.push({
|
||||
id: issue.id,
|
||||
title: `#${issue.number} - ${issue.title}`,
|
||||
description: "",
|
||||
project: p,
|
||||
labels: issue.labels,
|
||||
assignee: issue.assignee,
|
||||
number: issue.number
|
||||
});
|
||||
}
|
||||
|
||||
return projectCards;
|
||||
|
||||
}, laneCards);
|
||||
|
||||
}, []);
|
||||
}
|
||||
|
||||
function createLane(projects, issues, lane, index) {
|
||||
return {
|
||||
id: index,
|
||||
title: lane.title,
|
||||
cards: createCards(projects, issues, lane)
|
||||
}
|
||||
}
|
||||
|
||||
function createKanboard(board, issues) {
|
||||
if (!board) return null;
|
||||
|
||||
const kanboard = {
|
||||
id: board.id,
|
||||
lanes: board.lanes.map(createLane.bind(null, board.projects, issues)),
|
||||
};
|
||||
|
||||
return kanboard;
|
||||
}
|
3
client/src/store/sagas/logout.js
Normal file
3
client/src/store/sagas/logout.js
Normal file
@ -0,0 +1,3 @@
|
||||
export function* logoutSaga() {
|
||||
window.location = '/logout';
|
||||
}
|
16
client/src/store/sagas/projects.js
Normal file
16
client/src/store/sagas/projects.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { put, call } from 'redux-saga/effects';
|
||||
import { FETCH_PROJECTS_SUCCESS, FETCH_PROJECTS_FAILURE } from '../actions/projects';
|
||||
import { gitea } from '../../util/gitea';
|
||||
|
||||
export function* fetchProjectsSaga() {
|
||||
|
||||
let projects;
|
||||
try {
|
||||
projects = yield call(gitea.fetchUserProjects.bind(gitea))
|
||||
} catch(error) {
|
||||
yield put({ type: FETCH_PROJECTS_FAILURE, error });
|
||||
return;
|
||||
}
|
||||
|
||||
yield put({ type: FETCH_PROJECTS_SUCCESS, projects });
|
||||
}
|
@ -1,9 +1,28 @@
|
||||
import { all, takeEvery } from 'redux-saga/effects';
|
||||
import { handleFailedActionSaga } from './failure';
|
||||
import { all, takeEvery, takeLatest } from 'redux-saga/effects';
|
||||
import { failuresSaga } from './failure';
|
||||
import { FETCH_BOARDS_REQUEST, SAVE_BOARD_REQUEST } from '../actions/boards';
|
||||
import { fetchBoardsSaga, saveBoardSaga } from './boards';
|
||||
import { FETCH_ISSUES_REQUEST, ADD_LABEL_REQUEST, REMOVE_LABEL_REQUEST } from '../actions/issues';
|
||||
import { fetchIssuesSaga, addLabelSaga, removeLabelSaga } from './issues';
|
||||
import { FETCH_PROJECTS_REQUEST } from '../actions/projects';
|
||||
import { fetchProjectsSaga } from './projects';
|
||||
import { LOGOUT } from '../actions/logout';
|
||||
import { logoutSaga } from './logout';
|
||||
import { BUILD_KANBOARD_REQUEST, MOVE_CARD } from '../actions/kanboards';
|
||||
import { buildKanboardSaga, moveCardSaga } from './kanboards';
|
||||
|
||||
export function* rootSaga() {
|
||||
yield all([
|
||||
takeEvery(patternFromRegExp(/^.*_FAILURE/), handleFailedActionSaga),
|
||||
takeEvery(patternFromRegExp(/^.*_FAILURE/), failuresSaga),
|
||||
takeLatest(FETCH_BOARDS_REQUEST, fetchBoardsSaga),
|
||||
takeLatest(BUILD_KANBOARD_REQUEST, buildKanboardSaga),
|
||||
takeLatest(SAVE_BOARD_REQUEST, saveBoardSaga),
|
||||
takeLatest(FETCH_ISSUES_REQUEST, fetchIssuesSaga),
|
||||
takeLatest(FETCH_PROJECTS_REQUEST, fetchProjectsSaga),
|
||||
takeEvery(MOVE_CARD, moveCardSaga),
|
||||
takeEvery(ADD_LABEL_REQUEST, addLabelSaga),
|
||||
takeEvery(REMOVE_LABEL_REQUEST, removeLabelSaga),
|
||||
takeLatest(LOGOUT, logoutSaga)
|
||||
]);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user