Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/sync communicator #1725

Merged
merged 10 commits into from
Jul 3, 2024
3 changes: 2 additions & 1 deletion src/components/Account/Login/Login.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ export function login({ email, password, activatedData }, type = 'local') {
);

if (loginData.communicators && loginData.communicators.length) {
currentCommunicator = loginData.communicators[0];
currentCommunicator =
loginData.communicators[loginData.communicators.length - 1]; //use the latest communicator
tomivm marked this conversation as resolved.
Show resolved Hide resolved
}

const localBoardsIds = [];
Expand Down
94 changes: 91 additions & 3 deletions src/components/Communicator/Communicator.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ import {
UPDATE_API_COMMUNICATOR_STARTED,
GET_API_MY_COMMUNICATORS_SUCCESS,
GET_API_MY_COMMUNICATORS_FAILURE,
GET_API_MY_COMMUNICATORS_STARTED
GET_API_MY_COMMUNICATORS_STARTED,
SYNC_COMMUNICATORS
} from './Communicator.constants';
import { defaultCommunicatorID } from './Communicator.reducer';
import API from '../../api';
import shortid from 'shortid';
import moment from 'moment';
import { switchBoard } from '../Board/Board.actions';
import history from './../../history';

export function importCommunicator(communicator) {
return {
Expand Down Expand Up @@ -230,12 +234,15 @@ export function verifyAndUpsertCommunicator(
*/

export function getApiMyCommunicators() {
return dispatch => {
return async dispatch => {
dispatch(getApiMyCommunicatorsStarted());
return API.getCommunicators()
.then(res => {
dispatch(getApiMyCommunicatorsSuccess(res));
return res;

return dispatch(syncCommunicators(res.data)).catch(e => {
console.error(e);
});
tomivm marked this conversation as resolved.
Show resolved Hide resolved
})
.catch(err => {
dispatch(getApiMyCommunicatorsFailure(err.message));
Expand Down Expand Up @@ -291,3 +298,84 @@ export function updateDefaultBoardsIncluded(boardAlreadyIncludedData) {
defaultBoardsIncluded: boardAlreadyIncludedData
};
}

export function syncCommunicators(remoteCommunicators) {
const reconcileCommunicators = (local, remote) => {
if (local.lastEdited && remote.lastEdited) {
if (moment(local.lastEdited).isAfter(remote.lastEdited)) {
return local;
}
if (moment(local.lastEdited).isBefore(remote.lastEdited)) {
return remote;
}
if (moment(local.lastEdited).isSame(remote.lastEdited)) {
return remote;
}
}
return remote;
};
const getActiveCommunicator = getState => {
return getState().communicator.communicators.find(
c => c.id === getState().communicator.activeCommunicatorId
);
};

return async (dispatch, getState) => {
const localCommunicators = getState().communicator.communicators;
const updatedCommunicators = [...localCommunicators];

for (const remote of remoteCommunicators) {
const localIndex = localCommunicators.findIndex(
local => local.id === remote.id
);

if (localIndex !== -1) {
// If the communicator exists locally, reconcile the two
const reconciled = reconcileCommunicators(
localCommunicators[localIndex],
remote
);
if (reconciled === localCommunicators[localIndex]) {
// Local is more recent, update the server
try {
const res = await dispatch(
updateApiCommunicator(localCommunicators[localIndex])
);
updatedCommunicators[localIndex] = res;
} catch (e) {
console.error(e);
}
} else {
updatedCommunicators[localIndex] = reconciled;
}
} else {
// If the communicator does not exist locally, add it
updatedCommunicators.push(remote);
}
}

const activeCommunicatorId = getActiveCommunicator(getState).id ?? null;
const lastRemoteSavedCommunicatorId = remoteCommunicators[0].id ?? null; //The last communicator saved on the server
const needToChangeActiveCommunicator =
activeCommunicatorId !== lastRemoteSavedCommunicatorId &&
updatedCommunicators.length &&
updatedCommunicators.findIndex(
communicator => communicator.id === lastRemoteSavedCommunicatorId
) !== -1;
tomivm marked this conversation as resolved.
Show resolved Hide resolved

dispatch({
type: SYNC_COMMUNICATORS,
communicators: updatedCommunicators,
activeCommunicatorId: needToChangeActiveCommunicator
? remoteCommunicators[0].id
tomivm marked this conversation as resolved.
Show resolved Hide resolved
: activeCommunicatorId
});

if (needToChangeActiveCommunicator) {
const newActiveCommunicator = getActiveCommunicator(getState);
const rootBoard = newActiveCommunicator.rootBoard;
dispatch(switchBoard(rootBoard));
history.replace(rootBoard);
}
};
}
1 change: 1 addition & 0 deletions src/components/Communicator/Communicator.constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ export const GET_API_MY_COMMUNICATORS_FAILURE =
'cboard/Communicator/GET_API_MY_COMMUNICATORS_FAILURE';
export const GET_API_MY_COMMUNICATORS_STARTED =
'cboard/Communicator/GET_API_MY_COMMUNICATORS_STARTED';
export const SYNC_COMMUNICATORS = 'Communicator/SYNC_COMMUNICATORS';
61 changes: 39 additions & 22 deletions src/components/Communicator/Communicator.reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import {
UPDATE_API_COMMUNICATOR_STARTED,
GET_API_MY_COMMUNICATORS_SUCCESS,
GET_API_MY_COMMUNICATORS_FAILURE,
GET_API_MY_COMMUNICATORS_STARTED
GET_API_MY_COMMUNICATORS_STARTED,
SYNC_COMMUNICATORS
} from './Communicator.constants';
import { LOGIN_SUCCESS, LOGOUT } from '../Account/Login/Login.constants';
import moment from 'moment';

export const defaultCommunicatorID = 'cboard_default';
const initialState = {
Expand Down Expand Up @@ -55,9 +57,13 @@ function communicatorReducer(state = initialState, action) {
};

case CREATE_COMMUNICATOR:
const newCommunicator = {
...action.payload,
lastEdited: moment().format()
};
return {
...state,
communicators: state.communicators.concat(action.payload)
communicators: state.communicators.concat(newCommunicator)
};

case EDIT_COMMUNICATOR:
Expand All @@ -67,7 +73,11 @@ function communicatorReducer(state = initialState, action) {
let newState = { ...state };

if (communicatorIndex >= 0) {
newState.communicators[communicatorIndex] = action.payload;
const updatedCommunicator = {
...action.payload,
lastEdited: moment().format()
};
newState.communicators[communicatorIndex] = updatedCommunicator;
}

return newState;
Expand Down Expand Up @@ -96,6 +106,7 @@ function communicatorReducer(state = initialState, action) {
if (index !== -1) {
const updatedCommunicators = [...state.communicators];
updatedCommunicators[index].boards.push(action.boardId);
updatedCommunicators[index].lastEdited = moment().format();
return {
...state,
communicators: updatedCommunicators
Expand All @@ -112,6 +123,7 @@ function communicatorReducer(state = initialState, action) {
const bindex = activeCommunicator.boards.indexOf(action.boardId);
if (bindex !== -1) {
dupdatedCommunicators[index].boards.splice(bindex, 1);
dupdatedCommunicators[index].lastEdited = moment().format();
return {
...state,
communicators: dupdatedCommunicators
Expand All @@ -135,6 +147,7 @@ function communicatorReducer(state = initialState, action) {
1,
action.nextBoardId
);
updatedCommunicators[index].lastEdited = moment().format();
return {
...state,
communicators: updatedCommunicators
Expand Down Expand Up @@ -163,6 +176,7 @@ function communicatorReducer(state = initialState, action) {
updatedCommunicators[
index
].defaultBoardsIncluded = defaultBoardsIncluded;
updatedCommunicators[index].lastEdited = moment().format();

return {
...state,
Expand All @@ -179,6 +193,7 @@ function communicatorReducer(state = initialState, action) {
const updatedCommunicators = [...state.communicators];
updatedCommunicators[index].defaultBoardsIncluded =
action.defaultBoardsIncluded;
updatedCommunicators[index].lastEdited = moment().format();

return {
...state,
Expand All @@ -199,7 +214,11 @@ function communicatorReducer(state = initialState, action) {
: state.activeCommunicatorId,
communicators: state.communicators.map(communicator =>
communicator.id === action.communicatorId
? { ...communicator, id: action.communicator.id }
? {
...communicator,
id: action.communicator.id,
lastEdited: action.communicator.lastEdited
}
: communicator
)
};
Expand All @@ -216,7 +235,15 @@ function communicatorReducer(state = initialState, action) {
case UPDATE_API_COMMUNICATOR_SUCCESS:
return {
...state,
isFetching: false
isFetching: false,
communicators: state.communicators.map(communicator =>
communicator.id === action.communicator.id
? {
...communicator,
lastEdited: action.communicator.lastEdited
}
: communicator
)
};
case UPDATE_API_COMMUNICATOR_FAILURE:
return {
Expand All @@ -229,25 +256,9 @@ function communicatorReducer(state = initialState, action) {
isFetching: true
};
case GET_API_MY_COMMUNICATORS_SUCCESS:
let flag = false;
const myCommunicators = [...state.communicators];
for (let i = 0; i < action.communicators.data.length; i++) {
for (let j = 0; j < myCommunicators.length; j++) {
if (myCommunicators[j].id === action.communicators.data[i].id) {
myCommunicators[j].boards = action.communicators.data[i].boards;
flag = true;
break;
}
}
if (!flag) {
myCommunicators.push(action.communicators.data[i]);
flag = false;
}
}
return {
...state,
isFetching: false,
communicators: myCommunicators
isFetching: false
};
case GET_API_MY_COMMUNICATORS_FAILURE:
return {
Expand All @@ -259,6 +270,12 @@ function communicatorReducer(state = initialState, action) {
...state,
isFetching: true
};
case SYNC_COMMUNICATORS:
return {
...state,
communicators: action.communicators,
activeCommunicatorId: action.activeCommunicatorId
};
default:
return state;
}
Expand Down
Loading