mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Delete campaign feature
This commit is contained in:
parent
0675f85d32
commit
d27e3c2d34
@ -334,11 +334,26 @@ JSON;
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function deleteCampaign(SS_HTTPRequest $request) {
|
||||
$response = new SS_HTTPResponse();
|
||||
$response->addHeader('Content-Type', 'application/json');
|
||||
$response->setBody(Convert::raw2json(['campaign' => 'delete']));
|
||||
$id = $request->param('ID');
|
||||
if (!$id || !is_numeric($id)) {
|
||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 400))
|
||||
->addHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
return $response;
|
||||
$record = ChangeSet::get()->byID($id);
|
||||
if(!$record) {
|
||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 404))
|
||||
->addHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
if(!$record->canDelete()) {
|
||||
return (new SS_HTTPResponse(json_encode(['status' => 'error']), 401))
|
||||
->addHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
$record->delete();
|
||||
|
||||
return (new SS_HTTPResponse('', 204));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,15 +42,13 @@ class GridField extends SilverStripeComponent {
|
||||
|
||||
const columns = this.props.data.columns;
|
||||
|
||||
const actions = [
|
||||
<GridFieldAction icon={'cog'} handleClick={this.editRecord} />,
|
||||
<GridFieldAction icon={'cancel'} handleClick={this.deleteRecord} />
|
||||
];
|
||||
// TODO Replace with display: table based system
|
||||
const cellWidth = 5;
|
||||
const actionCellWidth = 2 * 36 + 12;
|
||||
|
||||
// Placeholder to align the headers correctly with the content
|
||||
const actionPlaceholder = <span key={'actionPlaceholder'} style={{width: actions.length * 36 + 12}} />;
|
||||
|
||||
const headerCells = columns.map((column, i) => <GridFieldHeaderCell key={i} width={column.width}>{column.name}</GridFieldHeaderCell>);
|
||||
const actionPlaceholder = <span key={'actionPlaceholder'} style={{width: actionCellWidth}} />;
|
||||
const headerCells = columns.map((column, i) => <GridFieldHeaderCell key={i} width={cellWidth}>{column.name}</GridFieldHeaderCell>);
|
||||
const header = <GridFieldHeader>{headerCells.concat(actionPlaceholder)}</GridFieldHeader>;
|
||||
|
||||
const rows = records.map((record, i) => {
|
||||
@ -60,11 +58,18 @@ class GridField extends SilverStripeComponent {
|
||||
return <GridFieldCell key={i} width={column.width}>{val}</GridFieldCell>
|
||||
});
|
||||
|
||||
var rowActions = actions.map((action, j) => {
|
||||
return Object.assign({}, action, {
|
||||
key: `action-${i}-${j}`
|
||||
});
|
||||
})
|
||||
var rowActions = [
|
||||
<GridFieldAction
|
||||
icon={'cog'}
|
||||
handleClick={this.editRecord.bind(this, record.ID)}
|
||||
key={"action-" + i + "-edit"}
|
||||
/>,
|
||||
<GridFieldAction
|
||||
icon={'cancel'}
|
||||
handleClick={this.deleteRecord.bind(this, record.ID)}
|
||||
key={"action-" + i + "-delete"}
|
||||
/>
|
||||
];
|
||||
|
||||
return <GridFieldRow key={i}>{cells.concat(rowActions)}</GridFieldRow>;
|
||||
});
|
||||
@ -74,12 +79,23 @@ class GridField extends SilverStripeComponent {
|
||||
);
|
||||
}
|
||||
|
||||
deleteRecord(event) {
|
||||
// delete record
|
||||
/**
|
||||
* @param number int
|
||||
* @param event
|
||||
*/
|
||||
deleteRecord(id, event) {
|
||||
event.preventDefault();
|
||||
this.props.actions.deleteRecord(
|
||||
this.props.data.recordType,
|
||||
id,
|
||||
this.props.data.itemDeleteEndpoint.method,
|
||||
this.props.data.itemDeleteEndpoint.url
|
||||
);
|
||||
}
|
||||
|
||||
editRecord(event) {
|
||||
// edit record
|
||||
event.preventDefault();
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,5 +4,8 @@ export default {
|
||||
DELETE_RECORD: 'DELETE_RECORD',
|
||||
FETCH_RECORDS_REQUEST: 'FETCH_RECORDS_REQUEST',
|
||||
FETCH_RECORDS_FAILURE: 'FETCH_RECORDS_FAILURE',
|
||||
FETCH_RECORDS_SUCCESS: 'FETCH_RECORDS_SUCCESS'
|
||||
FETCH_RECORDS_SUCCESS: 'FETCH_RECORDS_SUCCESS',
|
||||
DELETE_RECORD_REQUEST: 'DELETE_RECORD_REQUEST',
|
||||
DELETE_RECORD_FAILURE: 'DELETE_RECORD_FAILURE',
|
||||
DELETE_RECORD_SUCCESS: 'DELETE_RECORD_SUCCESS'
|
||||
};
|
||||
|
@ -2,21 +2,64 @@ import ACTION_TYPES from './action-types';
|
||||
import fetch from 'isomorphic-fetch';
|
||||
import backend from 'silverstripe-backend.js';
|
||||
|
||||
/**
|
||||
* Populate strings based on a whitelist.
|
||||
* Not using ES6 string interpolation because its too powerful
|
||||
* for user supplied data.
|
||||
*
|
||||
* Example: populate("foo/bar/:id", {id: 123}) => "foo/bar/123"
|
||||
*
|
||||
* @param string str A template string with ":<name>" notation.
|
||||
* @param object Map of names to values
|
||||
* @return string
|
||||
*/
|
||||
function populate(str, params) {
|
||||
let names = ['id'];
|
||||
return names.reduce((str, name) => str.replace(`:${name}`, params[name]), str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all records
|
||||
*
|
||||
* @param string recordType Type of record (the "class name")
|
||||
* @param string method HTTP methods
|
||||
* @param string method HTTP method
|
||||
* @param string url API endpoint
|
||||
*/
|
||||
export function fetchRecords(recordType, method, url) {
|
||||
let payload = {recordType: recordType};
|
||||
url = populate(url, payload);
|
||||
return (dispatch, getState) => {
|
||||
dispatch ({type: ACTION_TYPES.FETCH_RECORDS_REQUEST, payload: {recordType: recordType}});
|
||||
dispatch ({type: ACTION_TYPES.FETCH_RECORDS_REQUEST, payload: payload});
|
||||
return backend[method.toLowerCase()](url)
|
||||
.then(response => response.json())
|
||||
.then(json => dispatch({type: ACTION_TYPES.FETCH_RECORDS_SUCCESS, payload: {recordType: recordType, data: json}}))
|
||||
.then(json => {
|
||||
dispatch({type: ACTION_TYPES.FETCH_RECORDS_SUCCESS, payload: {recordType: recordType, data: json}})
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch({type: ACTION_TYPES.FETCH_RECORDS_FAILURE, payload: {error: err, recordType: recordType}})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a record
|
||||
*
|
||||
* @param string recordType Type of record (the "class name")
|
||||
* @param number id Database identifier
|
||||
* @param string method HTTP method
|
||||
* @param string url API endpoint
|
||||
*/
|
||||
export function deleteRecord(recordType, id, method, url) {
|
||||
let payload = {recordType: recordType, id: id};
|
||||
url = populate(url, payload);
|
||||
return (dispatch, getState) => {
|
||||
dispatch ({type: ACTION_TYPES.DELETE_RECORD_REQUEST, payload: payload});
|
||||
return backend[method.toLowerCase()](url)
|
||||
.then(json => {
|
||||
dispatch({type: ACTION_TYPES.DELETE_RECORD_SUCCESS, payload: {recordType: recordType, id: id}})
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch({type: ACTION_TYPES.DELETE_RECORD_FAILURE, payload: {error: err, recordType: recordType, id: id}})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ const initialState = {
|
||||
};
|
||||
|
||||
function recordsReducer(state = initialState, action) {
|
||||
let records;
|
||||
let recordType;
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case ACTION_TYPES.CREATE_RECORD:
|
||||
@ -29,9 +32,24 @@ function recordsReducer(state = initialState, action) {
|
||||
return state;
|
||||
|
||||
case ACTION_TYPES.FETCH_RECORDS_SUCCESS:
|
||||
let recordType = action.payload.recordType;
|
||||
recordType = action.payload.recordType;
|
||||
// TODO Automatic pluralisation from recordType
|
||||
let records = action.payload.data._embedded[recordType + 's'];
|
||||
records = action.payload.data._embedded[recordType + 's'];
|
||||
return deepFreeze(Object.assign({}, state, {
|
||||
[recordType]: records
|
||||
}));
|
||||
|
||||
case ACTION_TYPES.DELETE_RECORD_REQUEST:
|
||||
return state;
|
||||
|
||||
case ACTION_TYPES.DELETE_RECORD_FAILURE:
|
||||
return state;
|
||||
|
||||
case ACTION_TYPES.DELETE_RECORD_SUCCESS:
|
||||
recordType = action.payload.recordType;
|
||||
records = state[recordType]
|
||||
.filter(record => record.ID != action.payload.id)
|
||||
|
||||
return deepFreeze(Object.assign({}, state, {
|
||||
[recordType]: records
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user