+ {t(content)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ },
+);
+
+SortStep.propTypes = {
+ title: PropTypes.string.isRequired,
+ content: PropTypes.string.isRequired,
+ buttonContent: PropTypes.string.isRequired,
+ onConfirm: PropTypes.func.isRequired,
+ onBack: PropTypes.func,
+ selectedOption: PropTypes.string.isRequired,
+ setSelectedOption: PropTypes.func.isRequired,
+};
+
+SortStep.defaultProps = {
+ onBack: undefined,
+};
+
+export default SortStep;
diff --git a/client/src/components/SortStep/SortStep.module.scss b/client/src/components/SortStep/SortStep.module.scss
new file mode 100644
index 0000000..46135a9
--- /dev/null
+++ b/client/src/components/SortStep/SortStep.module.scss
@@ -0,0 +1,7 @@
+:global(#app) {
+ .content {
+ color: #212121;
+ padding-bottom: 6px;
+ padding-left: 2px;
+ }
+}
diff --git a/client/src/components/SortStep/index.js b/client/src/components/SortStep/index.js
new file mode 100644
index 0000000..4388a89
--- /dev/null
+++ b/client/src/components/SortStep/index.js
@@ -0,0 +1,3 @@
+import SortStep from './SortStep';
+
+export default SortStep;
diff --git a/client/src/constants/ActionTypes.js b/client/src/constants/ActionTypes.js
index 4b07530..5fdc430 100644
--- a/client/src/constants/ActionTypes.js
+++ b/client/src/constants/ActionTypes.js
@@ -172,6 +172,10 @@ export default {
LIST_DELETE__SUCCESS: 'LIST_DELETE__SUCCESS',
LIST_DELETE__FAILURE: 'LIST_DELETE__FAILURE',
LIST_DELETE_HANDLE: 'LIST_DELETE_HANDLE',
+ LIST_SORT: 'LIST_SORT',
+ LIST_SORT__SUCCESS: 'LIST_SORT__SUCCESS',
+ LIST_SORT__FAILURE: 'LIST_SORT__FAILURE',
+ LIST_SORT_HANDLE: 'LIST_SORT_HANDLE',
/* Cards */
diff --git a/client/src/constants/EntryActionTypes.js b/client/src/constants/EntryActionTypes.js
index 1a7f241..a43869d 100755
--- a/client/src/constants/EntryActionTypes.js
+++ b/client/src/constants/EntryActionTypes.js
@@ -120,6 +120,7 @@ export default {
LIST_MOVE: `${PREFIX}/LIST_MOVE`,
LIST_DELETE: `${PREFIX}/LIST_DELETE`,
LIST_DELETE_HANDLE: `${PREFIX}/LIST_DELETE_HANDLE`,
+ LIST_SORT_HANDLE: `${PREFIX}/LIST_SORT_HANDLE`,
/* Cards */
diff --git a/client/src/containers/BoardsContainer.js b/client/src/containers/BoardsContainer.js
index a8bbf2e..fcca8ec 100755
--- a/client/src/containers/BoardsContainer.js
+++ b/client/src/containers/BoardsContainer.js
@@ -24,6 +24,7 @@ const mapDispatchToProps = (dispatch) =>
onUpdate: entryActions.updateBoard,
onMove: entryActions.moveBoard,
onDelete: entryActions.deleteBoard,
+ onSort: entryActions.sortBoard,
},
dispatch,
);
diff --git a/client/src/containers/ListContainer.js b/client/src/containers/ListContainer.js
index cb2f6a0..f50afc0 100755
--- a/client/src/containers/ListContainer.js
+++ b/client/src/containers/ListContainer.js
@@ -35,6 +35,7 @@ const mapDispatchToProps = (dispatch, { id }) =>
onUpdate: (data) => entryActions.updateList(id, data),
onDelete: () => entryActions.deleteList(id),
onCardCreate: (data, autoOpen) => entryActions.createCard(id, data, autoOpen),
+ onSort: (data) => entryActions.sortList(id, data),
},
dispatch,
);
diff --git a/client/src/entry-actions/lists.js b/client/src/entry-actions/lists.js
index 97350c1..9c598e7 100755
--- a/client/src/entry-actions/lists.js
+++ b/client/src/entry-actions/lists.js
@@ -51,6 +51,13 @@ const handleListDelete = (list) => ({
},
});
+const handleListSort = (list) => ({
+ type: EntryActionTypes.LIST_SORT_HANDLE,
+ payload: {
+ list,
+ },
+});
+
export default {
createListInCurrentBoard,
handleListCreate,
@@ -59,4 +66,5 @@ export default {
moveList,
deleteList,
handleListDelete,
+ handleListSort,
};
diff --git a/client/src/locales/sv/core.js b/client/src/locales/sv/core.js
index 3416364..8478d03 100644
--- a/client/src/locales/sv/core.js
+++ b/client/src/locales/sv/core.js
@@ -32,6 +32,7 @@ export default {
'Är du säker på att du vill ta bort den här kommentaren?',
areYouSureYouWantToDeleteThisLabel: 'Är du säker på att du vill ta bort den här etiketten?',
areYouSureYouWantToDeleteThisList: 'Är du säker på att du vill ta bort den här listan?',
+ areYouSureYouWantToSortThisList: 'Är du säker på att du vill sortera den här listan?',
areYouSureYouWantToDeleteThisProject: 'Är du säker på att du vill ta bort det här projektet?',
areYouSureYouWantToDeleteThisTask: 'Är du säker på att du vill ta bort den här uppgiften?',
areYouSureYouWantToDeleteThisUser: 'Är du säker på att du vill ta bort den här användaren?',
@@ -129,6 +130,7 @@ export default {
selectList: 'Välj lista',
selectProject: 'Välj projekt',
settings: 'Inställningar',
+ sortList: 'Sortera listan',
stopwatch: 'Timer',
subscribeToMyOwnCardsByDefault: 'Prenumerera på mina egna kort som standard',
taskActions_title: 'Uppgiftsåtgärder',
@@ -205,6 +207,14 @@ export default {
save: 'Spara',
showAllAttachments: 'Visa alla bilagor ({{hidden}} dolda)',
showFewerAttachments: 'Visa färre bilagor',
+ sortByCreatedAt: ' Sortera på skapad',
+ sortByCreatorUserIdList: ' Sortera på skapad av',
+ sortByDueDateList: ' Sortera på förfallodatum',
+ sortByIdList: ' Sortera på id',
+ sortByPositionList: ' Sortera på position',
+ sortByTitleList: ' Sortera på titel',
+ sortByUpdatedAtList: ' Sortera på uppdaterad',
+ sortList: 'Sortera listan',
start: 'Starta',
stop: 'Stoppa',
subscribe: 'Prenumerera',
diff --git a/client/src/models/List.js b/client/src/models/List.js
index b634a66..8f11639 100755
--- a/client/src/models/List.js
+++ b/client/src/models/List.js
@@ -76,16 +76,77 @@ export default class extends BaseModel {
break;
}
+ case ActionTypes.LIST_SORT:
+ List.withId(payload.id).sortList();
+ break;
+ case ActionTypes.LIST_SORT__SUCCESS:
+ case ActionTypes.LIST_SORT_HANDLE: {
+ const listModel = List.withId(payload.list.id);
+
+ if (listModel) {
+ listModel.sortList();
+ }
+
+ break;
+ }
default:
}
}
- getOrderedCardsQuerySet() {
+ getOrderedByIdCardsQuerySet() {
+ return this.cards.orderBy('id');
+ }
+
+ getOrderedByPositionCardsQuerySet() {
return this.cards.orderBy('position');
}
+ getOrderedByTitelCardsQuerySet() {
+ return this.cards.orderBy('name');
+ }
+
+ getOrderedByCreatedAtCardsQuerySet() {
+ return this.cards.orderBy('createdAt');
+ }
+
+ getOrderedByUpdatedAtCardsQuerySet() {
+ return this.cards.orderBy('updatedAt');
+ }
+
+ getOrderedByDueDateCardsQuerySet() {
+ return this.cards.orderBy('dueDate');
+ }
+
getFilteredOrderedCardsModelArray() {
- let cardModels = this.getOrderedCardsQuerySet().toModelArray();
+ const sortby = this.selectedOption;
+
+ let cardModels = null;
+
+ switch (sortby) {
+ case 'name':
+ cardModels = this.getOrderedByTitelCardsQuerySet().toModelArray();
+ break;
+ case 'id':
+ cardModels = this.getOrderedByIdCardsQuerySet().toModelArray();
+ break;
+ case 'position':
+ cardModels = this.getOrderedByPositionCardsQuerySet().toModelArray();
+ break;
+ case 'createdAt':
+ cardModels = this.getOrderedByCreatedAtCardsQuerySet().toModelArray();
+ break;
+ case 'updatedAt':
+ cardModels = this.getOrderedByUpdatedAtCardsQuerySet().toModelArray();
+ break;
+ case 'dueDate':
+ cardModels = this.getOrderedByDueDateCardsQuerySet().toModelArray();
+ break;
+ case 'creatorUserId':
+ cardModels = this.getOrderedByDueDateCardsQuerySet().toModelArray();
+ break;
+ default:
+ cardModels = this.getOrderedByPositionCardsQuerySet().toModelArray();
+ }
const filterUserIds = this.board.filterUsers.toRefArray().map((user) => user.id);
const filterLabelIds = this.board.filterLabels.toRefArray().map((label) => label.id);
diff --git a/client/src/sagas/core/services/lists.js b/client/src/sagas/core/services/lists.js
index d9dd718..c630d41 100644
--- a/client/src/sagas/core/services/lists.js
+++ b/client/src/sagas/core/services/lists.js
@@ -61,6 +61,24 @@ export function* handleListUpdate(list) {
yield put(actions.handleListUpdate(list));
}
+export function* sortList(id, data) {
+ yield put(actions.sortList(id, data));
+
+ let list;
+ try {
+ ({ item: list } = yield call(request, api.sortList, id, data));
+ } catch (error) {
+ yield put(actions.sortList.failure(id, error));
+ return;
+ }
+
+ yield put(actions.sortList.success(list));
+}
+
+export function* handleListSort(list) {
+ yield put(actions.handleListSort(list));
+}
+
export function* moveList(id, index) {
const { boardId } = yield select(selectors.selectListById, id);
const position = yield select(selectors.selectNextListPosition, boardId, index, id);
diff --git a/client/src/sagas/core/watchers/lists.js b/client/src/sagas/core/watchers/lists.js
index 028881e..c7a6ad1 100644
--- a/client/src/sagas/core/watchers/lists.js
+++ b/client/src/sagas/core/watchers/lists.js
@@ -17,6 +17,9 @@ export default function* listsWatchers() {
takeEvery(EntryActionTypes.LIST_UPDATE_HANDLE, ({ payload: { list } }) =>
services.handleListUpdate(list),
),
+ takeEvery(EntryActionTypes.LIST_SORT_HANDLE, ({ payload: { list } }) =>
+ services.handleListSort(list),
+ ),
takeEvery(EntryActionTypes.LIST_MOVE, ({ payload: { id, index } }) =>
services.moveList(id, index),
),
diff --git a/client/src/sagas/core/watchers/socket.js b/client/src/sagas/core/watchers/socket.js
index ef6bed9..4b73dd2 100644
--- a/client/src/sagas/core/watchers/socket.js
+++ b/client/src/sagas/core/watchers/socket.js
@@ -84,6 +84,10 @@ const createSocketEventsChannel = () =>
emit(entryActions.handleListDelete(item));
};
+ const handleListSort = ({ item }) => {
+ emit(entryActions.handleListSort(item));
+ };
+
const handleLabelCreate = ({ item }) => {
emit(entryActions.handleLabelCreate(item));
};
@@ -193,6 +197,7 @@ const createSocketEventsChannel = () =>
socket.on('listCreate', handleListCreate);
socket.on('listUpdate', handleListUpdate);
socket.on('listDelete', handleListDelete);
+ socket.on('listSort', handleListSort);
socket.on('labelCreate', handleLabelCreate);
socket.on('labelUpdate', handleLabelUpdate);
@@ -249,6 +254,7 @@ const createSocketEventsChannel = () =>
socket.off('listCreate', handleListCreate);
socket.off('listUpdate', handleListUpdate);
socket.off('listDelete', handleListDelete);
+ socket.off('listSort', handleListSort);
socket.off('labelCreate', handleLabelCreate);
socket.off('labelUpdate', handleLabelUpdate);
diff --git a/package-lock.json b/package-lock.json
index 25768c5..228dd12 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2039,9 +2039,9 @@
}
},
"node_modules/yaml": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
- "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+ "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
"engines": {
"node": ">= 14"
}
@@ -3510,9 +3510,9 @@
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yaml": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
- "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg=="
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+ "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA=="
},
"yargs": {
"version": "17.6.2",