Hook up DBRP manager to backend
parent
2c874e4e53
commit
9280741773
|
@ -1,25 +1,25 @@
|
|||
import uuid from 'node-uuid';
|
||||
|
||||
import {
|
||||
getUsers as getUsersAJAX,
|
||||
getRoles as getRolesAJAX,
|
||||
getPermissions as getPermissionsAJAX,
|
||||
getDbsAndRps as getDbsAndRpsAJAX,
|
||||
createUser as createUserAJAX,
|
||||
createRole as createRoleAJAX,
|
||||
createDatabase as createDatabaseAJAX,
|
||||
createRetentionPolicy as createRetentionPolicyAJAX,
|
||||
deleteUser as deleteUserAJAX,
|
||||
deleteRole as deleteRoleAJAX,
|
||||
deleteDatabase as deleteDatabaseAJAX,
|
||||
deleteRetentionPolicy as deleteRetentionPolicyAJAX,
|
||||
updateRole as updateRoleAJAX,
|
||||
updateUser as updateUserAJAX,
|
||||
updateRetentionPolicy as updateRetentionPolicyAJAX,
|
||||
} from 'src/admin/apis'
|
||||
|
||||
import {
|
||||
killQuery as killQueryProxy,
|
||||
showDatabases,
|
||||
showRetentionPolicies,
|
||||
} from 'shared/apis/metaQuery'
|
||||
|
||||
import parseShowDatabases from 'src/shared/parsing/showDatabases'
|
||||
import parseShowRetentionPolicies from 'src/shared/parsing/showRetentionPolicies'
|
||||
import {publishNotification} from 'src/shared/actions/notifications';
|
||||
import {ADMIN_NOTIFICATION_DELAY} from 'src/admin/constants'
|
||||
|
||||
|
@ -94,6 +94,16 @@ export const syncDatabase = (stale, synced) => ({
|
|||
},
|
||||
})
|
||||
|
||||
export const syncRetentionPolicy = (database, stale, synced) => ({
|
||||
type: 'SYNC_RETENTION_POLICY',
|
||||
payload: {
|
||||
database,
|
||||
stale,
|
||||
synced,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
export const editUser = (user, updates) => ({
|
||||
type: 'EDIT_USER',
|
||||
payload: {
|
||||
|
@ -224,19 +234,8 @@ export const loadPermissionsAsync = (url) => async (dispatch) => {
|
|||
}
|
||||
|
||||
export const loadDBsAndRPsAsync = (url) => async (dispatch) => {
|
||||
const {data: dbs} = await showDatabases(url)
|
||||
const {databases} = parseShowDatabases(dbs)
|
||||
|
||||
const {data: {results}} = await showRetentionPolicies(url, databases)
|
||||
const retentionPolicies = results.map(parseShowRetentionPolicies)
|
||||
const rps = retentionPolicies.map(rp => rp.retentionPolicies)
|
||||
const dbsAndRps = databases.map((name, i) => ({
|
||||
name,
|
||||
links: {self: uuid.v4()},
|
||||
retentionPolicies: rps[i].map(rp => ({...rp, links: {self: uuid.v4()}})),
|
||||
}))
|
||||
|
||||
dispatch(loadDatabases(dbsAndRps))
|
||||
const {data: {databases}} = await getDbsAndRpsAJAX(url)
|
||||
dispatch(loadDatabases(databases))
|
||||
}
|
||||
|
||||
export const createUserAsync = (url, user) => async (dispatch) => {
|
||||
|
@ -265,10 +264,9 @@ export const createRoleAsync = (url, role) => async (dispatch) => {
|
|||
|
||||
export const createDatabaseAsync = (url, database) => async (dispatch) => {
|
||||
try {
|
||||
// TODO: implement once server is up
|
||||
// const {data} = await createDatabaseAJAX(url, database)
|
||||
const {data} = await createDatabaseAJAX(url, database)
|
||||
dispatch(syncDatabase(database, data))
|
||||
dispatch(publishNotification('success', 'Database created successfully'))
|
||||
// dispatch(syncDatabase(database, {...data, id: uuid.v4()}))
|
||||
} catch (error) {
|
||||
// undo optimistic update
|
||||
dispatch(publishNotification('error', `Failed to create database: ${error.data.message}`))
|
||||
|
@ -276,26 +274,24 @@ export const createDatabaseAsync = (url, database) => async (dispatch) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const createRetentionPolicyAsync = (url, retentionPolicy) => async (dispatch) => {
|
||||
export const createRetentionPolicyAsync = (database, retentionPolicy) => async (dispatch) => {
|
||||
try {
|
||||
// TODO: implement once server is up
|
||||
// const {data} = await createRetentionPolicyAJAX(url, retentionPolicy)
|
||||
const {data} = await createRetentionPolicyAJAX(database.links.retentionPolicies, retentionPolicy)
|
||||
dispatch(publishNotification('success', 'Retention policy created successfully'))
|
||||
// dispatch(syncRetentionPolicy(retentionPolicy, {...data, id: uuid.v4()}))
|
||||
dispatch(syncRetentionPolicy(database, retentionPolicy, data))
|
||||
} catch (error) {
|
||||
// undo optimistic update
|
||||
dispatch(publishNotification('error', `Failed to create retention policy: ${error.data.message}`))
|
||||
setTimeout(() => dispatch(removeRetentionPolicy(retentionPolicy)), ADMIN_NOTIFICATION_DELAY)
|
||||
setTimeout(() => dispatch(removeRetentionPolicy(database, retentionPolicy)), ADMIN_NOTIFICATION_DELAY)
|
||||
}
|
||||
}
|
||||
|
||||
export const updateRetentionPolicyAsync = (database, retentionPolicy, updates) => async (dispatch) => {
|
||||
try {
|
||||
// TODO: implement once server is up
|
||||
dispatch(editRetentionPolicy(database, retentionPolicy, updates))
|
||||
// const {data} = await createRetentionPolicyAJAX(url, retentionPolicy)
|
||||
const {data} = await updateRetentionPolicyAJAX(retentionPolicy.links.self, updates)
|
||||
dispatch(publishNotification('success', 'Retention policy updated successfully'))
|
||||
// dispatch(syncRetentionPolicy(retentionPolicy, {...data, id: uuid.v4()}))
|
||||
dispatch(syncRetentionPolicy(database, data))
|
||||
} catch (error) {
|
||||
dispatch(publishNotification('error', `Failed to update retention policy: ${error.data.message}`))
|
||||
}
|
||||
|
@ -326,16 +322,24 @@ export const deleteUserAsync = (user, addFlashMessage) => (dispatch) => {
|
|||
deleteUserAJAX(user.links.self, addFlashMessage, user.name)
|
||||
}
|
||||
|
||||
export const deleteDatabaseAsync = (url, database) => (dispatch) => {
|
||||
export const deleteDatabaseAsync = (database) => async (dispatch) => {
|
||||
dispatch(removeDatabase(database))
|
||||
dispatch(publishNotification('success', 'Database deleted'))
|
||||
try {
|
||||
await deleteDatabaseAJAX(database.links.self)
|
||||
} catch (error) {
|
||||
dispatch(publishNotification('error', `Failed to delete database: ${error.data.message}`))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement once server is up
|
||||
// try {
|
||||
// await deleteDatabaseAJAX(url, database.name)
|
||||
// } catch (error) {
|
||||
// dispatch(publishNotification('error', `Failed to delete database: ${error.data.message}`))
|
||||
// }
|
||||
export const deleteRetentionPolicyAsync = (database, retentionPolicy) => async (dispatch) => {
|
||||
dispatch(removeRetentionPolicy(database, retentionPolicy))
|
||||
dispatch(publishNotification('success', `Retention policy ${retentionPolicy.name} deleted`))
|
||||
try {
|
||||
await deleteRetentionPolicyAJAX(retentionPolicy.links.self)
|
||||
} catch (error) {
|
||||
dispatch(publishNotification('error', `Failed to delete retentionPolicy: ${error.data.message}`))
|
||||
}
|
||||
}
|
||||
|
||||
export const updateRoleUsersAsync = (role, users) => async (dispatch) => {
|
||||
|
|
|
@ -36,6 +36,18 @@ export const getPermissions = async (url) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const getDbsAndRps = async (url) => {
|
||||
try {
|
||||
return await AJAX({
|
||||
method: 'GET',
|
||||
url,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export const createUser = async (url, user) => {
|
||||
try {
|
||||
return await AJAX({
|
||||
|
@ -84,6 +96,17 @@ export const createRetentionPolicy = async (url, retentionPolicy) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const deleteRetentionPolicy = async (url) => {
|
||||
try {
|
||||
return await AJAX({
|
||||
method: 'DELETE',
|
||||
url,
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteRole = async (url, addFlashMessage, rolename) => {
|
||||
try {
|
||||
const response = await AJAX({
|
||||
|
@ -124,11 +147,11 @@ export const deleteUser = async (url, addFlashMessage, username) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const deleteDatabase = async (url, name) => {
|
||||
export const deleteDatabase = async (url) => {
|
||||
try {
|
||||
return await AJAX({
|
||||
method: 'DELETE',
|
||||
url: `${url}/${name}`,
|
||||
url,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
@ -167,3 +190,18 @@ export const updateUser = async (url, roles, permissions) => {
|
|||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export const updateRetentionPolicy = async (url, retentionPolicy) => {
|
||||
try {
|
||||
return await AJAX({
|
||||
method: 'PUT',
|
||||
url,
|
||||
data: {
|
||||
retentionPolicy,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ const DatabaseManager = ({
|
|||
onCreateRetentionPolicy,
|
||||
onUpdateRetentionPolicy,
|
||||
onRemoveRetentionPolicy,
|
||||
onDeleteRetentionPolicy,
|
||||
}) => {
|
||||
return (
|
||||
<div className="panel panel-info">
|
||||
|
@ -45,6 +46,7 @@ const DatabaseManager = ({
|
|||
onCreateRetentionPolicy={onCreateRetentionPolicy}
|
||||
onUpdateRetentionPolicy={onUpdateRetentionPolicy}
|
||||
onRemoveRetentionPolicy={onRemoveRetentionPolicy}
|
||||
onDeleteRetentionPolicy={onDeleteRetentionPolicy}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -78,6 +80,7 @@ DatabaseManager.propTypes = {
|
|||
onCreateRetentionPolicy: func,
|
||||
onUpdateRetentionPolicy: func,
|
||||
onRemoveRetentionPolicy: func,
|
||||
onDeleteRetentionPolicy: func,
|
||||
}
|
||||
|
||||
export default DatabaseManager
|
||||
|
|
|
@ -8,6 +8,7 @@ class DatabaseRow extends Component {
|
|||
super(props)
|
||||
this.state = {
|
||||
isEditing: false,
|
||||
isDeleting: false,
|
||||
}
|
||||
this.handleKeyDown = ::this.handleKeyDown
|
||||
this.handleClickOutside = ::this.handleClickOutside
|
||||
|
@ -16,6 +17,8 @@ class DatabaseRow extends Component {
|
|||
this.handleCreate = ::this.handleCreate
|
||||
this.handleUpdate = ::this.handleUpdate
|
||||
this.getInputValues = ::this.getInputValues
|
||||
this.handleStartDelete = ::this.handleStartDelete
|
||||
this.handleEndDelete = ::this.handleEndDelete
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
|
@ -30,12 +33,14 @@ class DatabaseRow extends Component {
|
|||
retentionPolicy: {name, duration, replication, isDefault, isNew},
|
||||
retentionPolicy,
|
||||
database,
|
||||
onDelete,
|
||||
isRFDisplayed,
|
||||
} = this.props
|
||||
const {isEditing, isDeleting} = this.state
|
||||
|
||||
const formattedDuration = formatInfiniteDuration(duration)
|
||||
|
||||
if (this.state.isEditing) {
|
||||
if (isEditing) {
|
||||
return (
|
||||
<tr>
|
||||
<td>
|
||||
|
@ -72,7 +77,7 @@ class DatabaseRow extends Component {
|
|||
name="name"
|
||||
type="number"
|
||||
min="1"
|
||||
defaultValue={replication}
|
||||
defaultValue={replication || 1}
|
||||
placeholder="how many nodes do you have"
|
||||
onKeyDown={(e) => this.handleKeyDown(e, database)}
|
||||
ref={(r) => this.replication = r}
|
||||
|
@ -95,9 +100,13 @@ class DatabaseRow extends Component {
|
|||
<td onClick={this.handleStartEdit}>{formattedDuration}</td>
|
||||
{isRFDisplayed ? <td onClick={this.handleStartEdit}>{replication}</td> : null}
|
||||
<td className="text-right">
|
||||
<button className="btn btn-xs btn-danger admin-table--delete">
|
||||
{`Delete ${name}`}
|
||||
</button>
|
||||
{
|
||||
isDeleting ?
|
||||
<YesNoButtons onConfirm={() => onDelete(database, retentionPolicy)} onCancel={this.handleEndDelete} /> :
|
||||
<button className="btn btn-xs btn-danger admin-table--delete" onClick={this.handleStartDelete}>
|
||||
{`Delete ${name}`}
|
||||
</button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
@ -105,6 +114,7 @@ class DatabaseRow extends Component {
|
|||
|
||||
handleClickOutside() {
|
||||
this.handleEndEdit()
|
||||
this.handleEndDelete()
|
||||
}
|
||||
|
||||
handleStartEdit() {
|
||||
|
@ -115,14 +125,22 @@ class DatabaseRow extends Component {
|
|||
this.setState({isEditing: false})
|
||||
}
|
||||
|
||||
handleStartDelete() {
|
||||
this.setState({isDeleting: true})
|
||||
}
|
||||
|
||||
handleEndDelete() {
|
||||
this.setState({isDeleting: false})
|
||||
}
|
||||
|
||||
handleCreate() {
|
||||
const {database, onCreate} = this.props
|
||||
const {database, retentionPolicy, onCreate} = this.props
|
||||
const validInputs = this.getInputValues()
|
||||
if (!validInputs) {
|
||||
return
|
||||
}
|
||||
|
||||
onCreate(database, validInputs)
|
||||
onCreate(database, {...retentionPolicy, ...validInputs})
|
||||
this.handleEndEdit()
|
||||
}
|
||||
|
||||
|
@ -205,6 +223,7 @@ DatabaseRow.propTypes = {
|
|||
onRemove: func,
|
||||
onCreate: func,
|
||||
onUpdate: func,
|
||||
onDelete: func,
|
||||
notify: func,
|
||||
isRFDisplayed: bool,
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ const DatabaseTable = ({
|
|||
onCreateRetentionPolicy,
|
||||
onUpdateRetentionPolicy,
|
||||
onRemoveRetentionPolicy,
|
||||
onDeleteRetentionPolicy,
|
||||
}) => {
|
||||
return (
|
||||
<div className="db-manager">
|
||||
|
@ -57,6 +58,7 @@ const DatabaseTable = ({
|
|||
onCreate={onCreateRetentionPolicy}
|
||||
onUpdate={onUpdateRetentionPolicy}
|
||||
onRemove={onRemoveRetentionPolicy}
|
||||
onDelete={onDeleteRetentionPolicy}
|
||||
isRFDisplayed={isRFDisplayed}
|
||||
/>
|
||||
)
|
||||
|
@ -84,6 +86,7 @@ DatabaseTable.propTypes = {
|
|||
onCreateRetentionPolicy: func,
|
||||
onUpdateRetentionPolicy: func,
|
||||
onRemoveRetentionPolicy: func,
|
||||
onDeleteRetentionPolicy: func,
|
||||
}
|
||||
|
||||
const DatabaseTableHeader = ({
|
||||
|
|
|
@ -15,9 +15,9 @@ class DatabaseManagerPage extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {source: {links: {proxy}}, actions} = this.props
|
||||
const {source: {links: {databases}}, actions} = this.props
|
||||
|
||||
actions.loadDBsAndRPsAsync(proxy)
|
||||
actions.loadDBsAndRPsAsync(databases)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -39,23 +39,24 @@ class DatabaseManagerPage extends Component {
|
|||
onCreateRetentionPolicy={actions.createRetentionPolicyAsync}
|
||||
onUpdateRetentionPolicy={actions.updateRetentionPolicyAsync}
|
||||
onRemoveRetentionPolicy={actions.removeRetentionPolicy}
|
||||
onDeleteRetentionPolicy={actions.deleteRetentionPolicyAsync}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
handleCreateDatabase(database) {
|
||||
const {actions, notify} = this.props
|
||||
const {actions, notify, source} = this.props
|
||||
|
||||
if (!database.name) {
|
||||
return notify('error', 'Database name cannot be blank')
|
||||
}
|
||||
|
||||
actions.createDatabaseAsync(database)
|
||||
actions.createDatabaseAsync(source.links.databases, database)
|
||||
}
|
||||
|
||||
handleKeyDownDatabase(e, database) {
|
||||
const {key} = e
|
||||
const {actions, notify} = this.props
|
||||
const {actions, notify, source} = this.props
|
||||
|
||||
if (key === 'Escape') {
|
||||
actions.removeDatabase(database)
|
||||
|
@ -66,13 +67,13 @@ class DatabaseManagerPage extends Component {
|
|||
return notify('error', 'Database name cannot be blank')
|
||||
}
|
||||
|
||||
actions.createDatabaseAsync(database)
|
||||
actions.createDatabaseAsync(source.links.databases, database)
|
||||
}
|
||||
}
|
||||
|
||||
handleDatabaseDeleteConfirm(database, e) {
|
||||
const {key, target: {value}} = e
|
||||
const {actions, source, notify} = this.props
|
||||
const {actions, notify} = this.props
|
||||
|
||||
if (key === 'Escape') {
|
||||
return actions.removeDatabaseDeleteCode(database)
|
||||
|
@ -83,7 +84,7 @@ class DatabaseManagerPage extends Component {
|
|||
return notify('error', `Please type DELETE ${database.name} to confirm`)
|
||||
}
|
||||
|
||||
return actions.deleteDatabaseAsync(source, database)
|
||||
return actions.deleteDatabaseAsync(database)
|
||||
}
|
||||
|
||||
actions.editDatabase(database, {deleteCode: value})
|
||||
|
@ -125,6 +126,7 @@ DatabaseManagerPage.propTypes = {
|
|||
startDeleteDatabase: func,
|
||||
removeDatabaseDeleteCode: func,
|
||||
removeRetentionPolicy: func,
|
||||
deleteRetentionPolicyAsync: func,
|
||||
}),
|
||||
notify: func,
|
||||
}
|
||||
|
|
|
@ -99,6 +99,19 @@ export default function admin(state = initialState, action) {
|
|||
const newState = {
|
||||
databases: state.databases.map(db => db.links.self === stale.links.self ? {...synced} : db),
|
||||
}
|
||||
|
||||
return {...state, ...newState}
|
||||
}
|
||||
|
||||
case 'SYNC_RETENTION_POLICY': {
|
||||
const {database, stale, synced} = action.payload
|
||||
const newState = {
|
||||
databases: state.databases.map(db => db.links.self === database.links.self ? {
|
||||
...db,
|
||||
retentionPolicies: db.retentionPolicies.map(rp => rp.links.self === stale.links.self ? {...synced} : rp),
|
||||
} : db),
|
||||
}
|
||||
|
||||
return {...state, ...newState}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue