Skip to content
This repository has been archived by the owner on Jan 4, 2019. It is now read-only.

Commit

Permalink
Release/3.2.0 (#41)
Browse files Browse the repository at this point in the history
* [KFI]fix(Epics): Remove requestContent call from the initSensenetStoreEpic

* [KFI]fix(Reducers): Fix userAvatarPath

For now userAvatarPath contains the Avatar field's value so it doesn't matter if the avatar is a
binary or a reference

* [KFI]test(ReducerTests): Fix userAvatarPath test

* [KFI]fix(Reducers): Fix fetch getError and order reducers

* [KFI]feat(Actions): Add two new Actions for selection and deselecting a Content

* [KFI]feat(Reducers): Change selected reducer to handle select and deselect actions

* [KFI]test(Actions): Add tests for select and deselect actions

* [KFI]test(Reducers): Add test for testing the selected Reducer handling select and deselect Actions

* [KFI]feat(Actions): Add actions for getting sn Actions of a content

* [KFI]test(Actions): Add tests for testing the new sn action getter Actions

* [KFI]feat(Reducers): Complete the Reducer of the content items

* [KFI]test(Reducers): Add test for testing the childrenactions reducer

* [KFI]feat(Reducers): Add a isOpened reducer

This reducer holds the id of the content where the actionmenu was opened last

* [KFI]fix(Reducers): Change action in isOpened reducer to REQUEST_CONTENT_ACTION

* [KFI]test(Reducers): Add test for testing isOpened reducer

* [KFI]feat(Reducers): Add a function to return the currently opened items id

* [KFI]refactor(Reducer): Rename getOpenedContentId to getOpenedContent

* [KFI]test(Reducers): Add a test for testing getOpenedContent function

* [KFI]feat(Actions): Add id as input attr to RequestContentActions Action

* [KFI]feat(Reducers): Add getChildrenActions function to return actions from the state tree

* [KFI]feat(Actions): Change RequestContentActions first input param to content

* [KFI]feat(Epics): Add getContentActions Epic

* [KFI]fix(GetActions): Fix GetActions action

* [KFI]feat(Reducers): Add getCurrentContent to get the path of the current content

* [KFI]fix(Epics): Fix loadContentActions epic

* [KFI]test: Improve epic tests

* [KFI]chore: Update version number
  • Loading branch information
herflis authored Sep 19, 2017
1 parent 57e5b4e commit 61a38d0
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 52 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sn-redux",
"version": "3.1.1",
"version": "3.2.0",
"description": "A set of redux actions, reducers and redux-ovbservable epics for Sense/Net ECM",
"main": "dist/src/sn-redux.js",
"scripts": {
Expand Down
49 changes: 49 additions & 0 deletions src/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,53 @@ export module Actions {
type: 'LOAD_REPOSITORY',
repository: repositoryConfig
})
/**
* Action creator for selecting a Content
* @param id {number} The id of the selected Content
* @returns {Object} Returns a redux action.
*/
export const SelectContent = (id) => ({
type: 'SELECT_CONTENT',
id
})
/**
* Action creator for deselecting a Content
* @param id {number} The id of the deselected Content
* @returns {Object} Returns a redux action.
*/
export const DeSelectContent = (id) => ({
type: 'DESELECT_CONTENT',
id
})
/**
* Action creator for a request for get actions of a content by a given scenario.
* @param content {Content} The name of the scenario
* @param scenario {string} The name of the scenario
* @returns {Object} Returns a redux action.
*/
export const RequestContentActions = (content, scenario?: string) => ({
type: 'REQUEST_CONTENT_ACTIONS',
content,
scenario
})
/**
* Action creator for the step getting the actions of a content successfully.
* @param response {any} JSON response of the ajax request.
* @returns {Object} Returns a redux action with a response.
*/
export const RequestContentActionsSuccess = (response: any, id: number) => {
return ({
type: 'REQUEST_CONTENT_ACTIONS_SUCCESS',
response: response,
id
})}
/**
* Action creator for the step when getting the actions of a content is failed
* @param error {any} JSON response of the ajax request.
* @returns {Object} Returns a redux action with a response.
*/
export const RequestContentActionsFailure = (error: any) => ({
type: 'REQUEST_CONTENT_ACTIONS_FAILURE',
message: error.message
})
}
20 changes: 15 additions & 5 deletions src/Epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Reducers } from './Reducers';

import { ActionsObservable, combineEpics } from 'redux-observable';
import { Observable } from '@reactivex/rxjs';
import { Repository, Content, Collection, ODataApi, Authentication } from 'sn-client-js';
import { Repository, Content, ContentTypes, Collection, ODataApi, Authentication } from 'sn-client-js';

/**
* Module for redux-observable Epics of the sensenet built-in OData actions.
Expand Down Expand Up @@ -50,7 +50,6 @@ export module Epics {
store.dispatch(Actions.LoadRepository(dependencies.repository.Config))
return dependencies.repository.Load(action.path, action.options)
.map((response) => {
store.dispatch(Actions.RequestContent(action.path, action.options))
return Actions.ReceiveLoadedContent(response, action.options)
})
.catch(error => {
Expand Down Expand Up @@ -99,8 +98,9 @@ export module Epics {
export const loadContentActionsEpic = (action$, store, dependencies?: { repository: Repository.BaseRepository }) => {
return action$.ofType('LOAD_CONTENT_ACTIONS')
.mergeMap(action => {
return action.content.Actions(action.scenario)
.map(Actions.ReceiveContentActions)
let c = dependencies.repository.HandleLoadedContent(action.content, ContentTypes.GenericContent);
return c.Actions(action.scenario)
.map(result => Actions.ReceiveContentActions(result))
.catch(error => Observable.of(Actions.ReceiveContentActionsFailure(error)))
})
}
Expand Down Expand Up @@ -335,6 +335,15 @@ export module Epics {
.catch(error => Observable.of(Actions.UserLogoutFailure(error)))
})
}
export const getContentActions = (action$, store, dependencies?: { repository: Repository.BaseRepository }) => {
return action$.ofType('REQUEST_CONTENT_ACTIONS')
.mergeMap(action => {
let c = dependencies.repository.HandleLoadedContent(action.content, ContentTypes.GenericContent);
return c.Actions(action.scenario)
.map(result => Actions.RequestContentActionsSuccess(result, action.content.Id))
.catch(error => Observable.of(Actions.RequestContentActionsFailure(error)))
})
}
/**
* sn-redux root Epic, the main Epic combination that is used on a default sensenet application. Contains Epics related to CRUD operations and thr other built-in sensenet
* [OData Actions and Function](http://wiki.sensenet.com/Built-in_OData_actions_and_functions).
Expand All @@ -358,7 +367,8 @@ export module Epics {
restoreversionContentEpic,
userLoginEpic,
userLogoutEpic,
checkLoginStateEpic
checkLoginStateEpic,
getContentActions
);
}

90 changes: 55 additions & 35 deletions src/Reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,13 @@ export module Reducers {
export const userAvatarPath = (state = '', action) => {
switch (action.type) {
case 'USER_CHANGED':
return action.user.ImageData ? action.user.ImageData.__mediaresource.media_src : ''
return action.user.Avatar ? action.user.Avatar._deferred : ''
default:
return state
}
}

/**
* Reducer combining userName, fullName and userLanguage into a single object, ```user```.
* Reducer combining userName, fullName, userLanguage, userAvatarPath into a single object, ```user```.
*/
const user = combineReducers({
userName,
Expand Down Expand Up @@ -195,7 +194,7 @@ export module Reducers {
* @returns {Object} state. Returns the next state based on the action.
*/
export const entities = (state = {}, action) => {
if (action.response && (action.type !== 'USER_LOGIN_SUCCESS' && action.type !== 'LOAD_CONTENT_SUCCESS')) {
if (action.response && (action.type !== 'USER_LOGIN_SUCCESS' && action.type !== 'LOAD_CONTENT_SUCCESS' && action.type !== 'REQUEST_CONTENT_ACTIONS_SUCCESS')) {
return (<any>Object).assign({}, state, action.response.entities.entities);
}
switch (action.type) {
Expand Down Expand Up @@ -234,40 +233,17 @@ export module Reducers {
switch (action.type) {
case 'FETCH_CONTENT_FAILURE':
return action.message;
case 'CREATE_CONTENT_FAILURE':
case 'UPDATE_CONTENT_FAILURE':
case 'DELETE_CONTENT_FAILURE':
case 'CHECKIN_CONTENT_FAILURE':
case 'CHECKOUT_CONTENT_FAILURE':
case 'PUBLISH_CONTENT_FAILURE':
case 'APPROVE_CONTENT_FAILURE':
case 'REJECT_CONTENT_FAILURE':
case 'UNDOCHECKOUT_CONTENT_FAILURE':
case 'FORCEUNDOCHECKOUT_CONTENT_FAILURE':
case 'RESTOREVERSION_CONTENT_FAILURE':
case 'FETCH_CONTENT_REQUEST':
case 'FETCH_CONTENT_SUCCESS':
case 'CREATE_CONTENT_REQUEST':
case 'CREATE_CONTENT_SUCCESS':
case 'UPDATE_CONTENT_REQUEST':
case 'UPDATE_CONTENT_SUCCESS':
case 'DELETE_CONTENT_REQUEST':
case 'DELETE_CONTENT_SUCCESS':
case 'CHECKIN_CONTENT_REQUEST':
case 'CHECKIN_CONTENT_SUCCESS':
case 'CHECKOUT_CONTENT_REQUEST':
case 'CHECKOUT_CONTENT_SUCCESS':
case 'APPROVE_CONTENT_REQUEST':
case 'APPROVE_CONTENT_SUCCESS':
case 'PUBLISH_CONTENT_REQUEST':
case 'PUBLISH_CONTENT_SUCCESS':
case 'REJECT_CONTENT_REQUEST':
case 'REJECT_CONTENT_SUCCESS':
case 'UNDOCHECKOUT_CONTENT_REQUEST':
case 'UNDOCHECKOUT_CONTENT_SUCCESS':
case 'FORCEUNDOCHECKOUT_CONTENT_REQUEST':
case 'FORCEUNDOCHECKOUT_CONTENT_SUCCESS':
case 'RESTOREVERSION_CONTENT_REQUEST':
case 'RESTOREVERSION_CONTENT_SUCCESS':
return null;
default:
Expand All @@ -280,8 +256,13 @@ export module Reducers {
* @param {Object} action Represents an action that is called.
* @returns {Object} state. Returns the next state based on the action.
*/
export const childrenactions = (state = {}, action) => {
return state
export const childrenactions = (state = [], action) => {
switch (action.type) {
case 'REQUEST_CONTENT_ACTIONS_SUCCESS':
return action.response
default:
return state
}
}
/**
* Reducer to handle Actions on the top property in the children object.
Expand Down Expand Up @@ -343,8 +324,8 @@ export module Reducers {
export const order = (state = {}, action) => {
switch (action.type) {
case 'FETCH_CONTENT_REQUEST':
if (action.options.order)
return action.options.order
if (action.options.orderby)
return action.options.orderby
else
return state
default:
Expand Down Expand Up @@ -385,6 +366,20 @@ export module Reducers {
return state
}
}
/**
* Reducer to handle Actions on the isOpened property in the children object.
* @param {Object} [state={}] Represents the current state.
* @param {Object} action Represents an action that is called.
* @returns {Object} state. Returns the next state based on the action.
*/
export const isOpened = (state = null, action) => {
switch (action.type) {
case 'REQUEST_CONTENT_ACTIONS_SUCCESS':
return action.id
default:
return state
}
}
/**
* Reducer combining ids, entities, isFetching, error, top, skip, query, order, filter and select into a single object, ```children```.
*/
Expand All @@ -393,13 +388,14 @@ export module Reducers {
entities,
isFetching,
error: childrenerror,
// actions: childrenactions,
actions: childrenactions,
top,
skip,
query,
order,
filter,
select
select,
isOpened
})
/**
* Reducer to handle Actions on the isSaved property in the contentState object.
Expand Down Expand Up @@ -575,7 +571,15 @@ export module Reducers {
* @returns {Object} state. Returns the next state based on the action.
*/
export const selected = (state = [], action) => {
return state;
switch (action.type) {
case 'SELECT_CONTENT':
return [...state, action.id]
case 'DESELECT_CONTENT':
const index = state.indexOf(action.id)
return [...state.slice(0, index), ...state.slice(index + 1)]
default:
return state
}
}
/**
* Reducer combining session, children, currentcontent and selected into a single object, ```sensenet``` which will be the top-level one.
Expand Down Expand Up @@ -612,7 +616,7 @@ export module Reducers {
* @returns {string} Returns the error message.
*/
export const getError = (state: any) => {
return state.errorMessage
return state.error
};

export const getAuthenticationStatus = (state) => {
Expand All @@ -626,4 +630,20 @@ export module Reducers {
export const getRepositoryUrl = (state) => {
return state.session.repository.RepositoryUrl;
}

export const getSelectedContent = (state) => {
return state.selected
}

export const getOpenedContent = (state) => {
return state.isOpened
}

export const getChildrenActions = (state) => {
return state.actions
}

export const getCurrentContent = (state) => {
return state.currentcontent.content
}
}
49 changes: 49 additions & 0 deletions test/ActionsTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,53 @@ describe('Actions', () => {
expect(Actions.LoadRepository(repo)).to.deep.equal(expectedAction)
});
});
describe('SelectContent', () => {
it('should return the select content action', () => {
const expectedAction = {
type: 'SELECT_CONTENT',
id: 1
}
expect(Actions.SelectContent(1)).to.deep.equal(expectedAction)
})
})
describe('DeSelectContent', () => {
it('should return the deselect content action', () => {
const expectedAction = {
type: 'DESELECT_CONTENT',
id: 1
}
expect(Actions.DeSelectContent(1)).to.deep.equal(expectedAction)
})
})
describe('RequestContentActions', () => {

const content = Content.Create({ DisplayName: 'My content', Id: 123 }, ContentTypes.Task, repo)
it('should return the RequestContentActions action', () => {
const expectedAction = {
type: 'REQUEST_CONTENT_ACTIONS',
content: content,
scenario: 'DMSListItem'
}
expect(Actions.RequestContentActions(content, 'DMSListItem')).to.deep.equal(expectedAction)
})
it('should return the RequestContentActionsSuccess action', () => {
const expectedAction = {
type: 'REQUEST_CONTENT_ACTIONS_SUCCESS',
response: [
{
ActionName: 'Rename'
}
],
id: 1
}
expect(Actions.RequestContentActionsSuccess([{ ActionName: 'Rename' }], 1)).to.deep.equal(expectedAction)
})
it('should return the RequestContentActionsFailure action', () => {
const expectedAction = {
type: 'REQUEST_CONTENT_ACTIONS_FAILURE',
message: 'error'
}
expect(Actions.RequestContentActionsFailure({ message: 'error' })).to.deep.equal(expectedAction)
});
})
});
Loading

0 comments on commit 61a38d0

Please sign in to comment.