-
Notifications
You must be signed in to change notification settings - Fork 46
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/versioning #225
Merged
Merged
Feature/versioning #225
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
e693798
feat: initial implementation of the versioning logic
StyleT 2587ba0
chore: code refactoring
StyleT 10ecef2
fix: Fixed data formation for log record
StyleT fce5251
feat: ability to log creation of the record with auto-increment ID
StyleT 780ceb1
feat: initial implementation of the version revert logic
StyleT beea4aa
feat: added API to list available versions
StyleT 353a2ff
chore: code refactoring
StyleT 95c2fc0
chore: better typings
StyleT e6b1735
Basic UI implementation
StyleT 2ed616e
feat: versioning UI enhancements
StyleT a3f8874
chore: debug logging removed
StyleT 27ad46a
chore: Fixed authEntity password update from UI
StyleT 5996542
feat: added versioning for auth entities
StyleT 7b58b68
feat: added versioning for settings
StyleT d2f2414
feat: added versioning for shared_props
StyleT 6e67224
feat: added versioning for templates
StyleT 9f7c44f
chore: bugfix
StyleT 6ea55ce
chore: added initial tests for versioning service
StyleT 6c3fcf3
chore: unit tests for versioning
StyleT 27c6933
chore: API tests for versioning added
StyleT ee4bb41
chore: moved typings to related package
StyleT 3cf2084
chore: removal of the magic strings
StyleT f6e4c8e
chore: refined interfaces
StyleT File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {setOperations} from "../dataProvider"; | ||
|
||
export function transformGet(entity) { | ||
|
||
} | ||
|
||
export function transformSet(entity, operation) { | ||
if (operation === setOperations.update) { | ||
delete entity.id; | ||
delete entity.identifier; | ||
delete entity.provider; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
import _ from 'lodash/fp'; | ||
|
||
/** | ||
* Original source code was taken from {@link https://github.com/prototypejs/prototype/blob/5fddd3e/src/prototype/lang/string.js#L702} | ||
*/ | ||
const isJSON = (str) => { | ||
if (/^\s*$/.test(str)) return false; | ||
|
||
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); | ||
str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); | ||
str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); | ||
|
||
return (/^[\],:{}\s]*$/).test(str); | ||
}; | ||
|
||
const parse = (value) => { | ||
if (_.isString(value) && isJSON(value)) { | ||
return JSON.parse(value); | ||
} | ||
|
||
return value; | ||
} | ||
|
||
export function parseJSON(value) { | ||
return _.cond([ | ||
[_.isArray, _.map(_.mapValues(parseJSON))], | ||
[_.isObject, _.mapValues(parseJSON)], | ||
[_.stubTrue, parse] | ||
])(value); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import React, {Children, cloneElement, useState, useCallback} from 'react'; | ||
import {makeStyles} from '@material-ui/core'; | ||
import ReactDiffViewer from 'react-diff-viewer'; | ||
import { | ||
List, | ||
Datagrid, | ||
Button, | ||
TextField, | ||
SelectInput, | ||
TextInput, | ||
Filter, | ||
FunctionField, | ||
useRefresh, | ||
useNotify | ||
} from 'react-admin'; | ||
import {parseJSON} from '../utils/json'; | ||
import {SettingsBackupRestore} from "@material-ui/icons"; | ||
|
||
const ListActionsToolbar = ({children, ...props}) => { | ||
const classes = makeStyles({ | ||
toolbar: { | ||
alignItems: 'center', | ||
display: 'flex', | ||
marginTop: -1, | ||
marginBottom: -1, | ||
}, | ||
}); | ||
|
||
return ( | ||
<div className={classes.toolbar}> | ||
{Children.map(children, button => cloneElement(button, props))} | ||
</div> | ||
); | ||
}; | ||
|
||
const MyFilter = (props) => ( | ||
<Filter {...props}> | ||
<SelectInput label="Entity Type" source="entity_type" choices={[{id: 'apps', name: 'Apps'}, {id: 'routes', name: 'Routes'}]} alwaysOn/> | ||
<TextInput label="Entity ID" source="entity_id" alwaysOn /> | ||
<TextInput label="Created by" source="created_by" alwaysOn /> | ||
</Filter> | ||
); | ||
|
||
const beautifyJson = v => JSON.stringify(parseJSON(JSON.parse(v)), null, 2); | ||
|
||
|
||
const MyPanel = ({ id, record, resource }) => ( | ||
<ReactDiffViewer | ||
oldValue={beautifyJson(record.data || record.data_after)} | ||
newValue={beautifyJson(record.data_after || record.data)} | ||
splitView={false} | ||
showDiffOnly={false} | ||
compareMethod={'diffWords'} | ||
styles={{ | ||
diffContainer: { | ||
pre: { | ||
lineHeight: '1', | ||
}, | ||
}, | ||
gutter: { | ||
minWidth: 0, | ||
} | ||
}} | ||
/> | ||
); | ||
|
||
const RevertButton = ({ | ||
record, | ||
...rest | ||
}) => { | ||
const [disabled, setDisabled] = useState(false); | ||
const refresh = useRefresh(); | ||
const notify = useNotify(); | ||
|
||
const handleClick = useCallback(() => { | ||
if (confirm(`Are you sure that you want to revert change with ID "${record.id}"?`)) { | ||
setDisabled(true); | ||
fetch(`/api/v1/versioning/${record.id}/revert`, {method: 'POST'}).then(async res => { | ||
setDisabled(false); | ||
if (!res.ok) { | ||
if (res.status < 500) { | ||
const resInfo = await res.json(); | ||
return notify(resInfo.reason, 'error', { smart_count: 1 }); | ||
} | ||
throw new Error(`Unexpected network error. Returned code "${res.status}"`); | ||
} | ||
notify('Change was successfully reverted', 'info', { smart_count: 1 }); | ||
refresh(); | ||
}).catch(err => { | ||
setDisabled(false); | ||
notify('Oops! Something went wrong.', 'error', { smart_count: 1 }); | ||
console.error(err); | ||
}); | ||
} | ||
}, []); | ||
|
||
return ( | ||
<Button | ||
label="Revert" | ||
disabled={disabled} | ||
onClick={handleClick} | ||
{...rest} | ||
> | ||
<SettingsBackupRestore/> | ||
</Button> | ||
); | ||
}; | ||
|
||
const PostList = props => { | ||
return ( | ||
<List | ||
{...props} | ||
title="History" | ||
filters={<MyFilter/>} | ||
exporter={false} | ||
perPage={25} | ||
bulkActionButtons={false} | ||
> | ||
<Datagrid expand={<MyPanel />} > | ||
<TextField sortable={false} source="id" /> | ||
<TextField sortable={false} source="entity_type" /> | ||
<TextField sortable={false} source="entity_id" /> | ||
<FunctionField label="Operation" render={record => record.data && record.data_after ? 'UPDATE' : record.data ? 'DELETE' : 'CREATE'} /> | ||
<TextField sortable={false} source="created_by" /> | ||
<FunctionField label="Created At" render={record => new Date(record.created_at * 1000).toLocaleString()} /> | ||
<ListActionsToolbar> | ||
<RevertButton /> | ||
</ListActionsToolbar> | ||
</Datagrid> | ||
</List> | ||
); | ||
}; | ||
|
||
export default PostList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export function transformGet(setting) { | ||
|
||
} | ||
|
||
export function transformSet(setting) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Icon from '@material-ui/icons/History'; | ||
import React, {Children, cloneElement} from 'react'; | ||
|
||
import List from './List'; | ||
|
||
export default { | ||
list: List, | ||
icon: Icon, | ||
options: {label: 'History'}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if you create an object that I mentioned here you could use it here with
toUpperCase()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that using here the same variable is a little bit incorrect since it's
View
with simple textual information which can be changed. So it's better to not mix presentation and logic inside a single variable.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree with that