-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes #1070 - Implementation of a formatted view for scopes in the g…
…raphical configuration view (#1096)
- Loading branch information
Showing
10 changed files
with
413 additions
and
7 deletions.
There are no files selected for viewing
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
55 changes: 55 additions & 0 deletions
55
...configurationserver-ui/src/components/editor/method-configuration-editor/HighlightText.js
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,55 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const AVAILABLE_THEMES = ['gray', 'blue', 'yellow', 'green']; | ||
|
||
/** | ||
* Component for showing a highlighted text element. | ||
*/ | ||
const HighlightText = ({ value, theme }) => { | ||
const themeClass = AVAILABLE_THEMES.includes(theme) ? theme : AVAILABLE_THEMES[0]; | ||
|
||
return ( | ||
<> | ||
<style jsx>{` | ||
span { | ||
font-family: monospace; | ||
padding: 0.1rem 0.5rem; | ||
border-radius: 0.2rem; | ||
font-weight: 700; | ||
} | ||
.gray { | ||
color: #333333; | ||
background-color: #e6e6e6; | ||
} | ||
.blue { | ||
color: #466594; | ||
background-color: #cfe2ff; | ||
} | ||
.yellow { | ||
color: #805b36; | ||
background-color: #ffd8b2; | ||
} | ||
.green { | ||
color: #256029; | ||
background-color: #c8e6c9; | ||
} | ||
`}</style> | ||
<span className={themeClass}>{value}</span> | ||
</> | ||
); | ||
}; | ||
|
||
HighlightText.propTypes = { | ||
/** The text to show. */ | ||
value: PropTypes.string, | ||
/** The color theme to use */ | ||
theme: PropTypes.oneOf(AVAILABLE_THEMES), | ||
}; | ||
|
||
HighlightText.defaultProps = { | ||
value: null, | ||
theme: 'gray', | ||
}; | ||
|
||
export default HighlightText; |
33 changes: 33 additions & 0 deletions
33
...ationserver-ui/src/components/editor/method-configuration-editor/HighlightText.stories.js
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,33 @@ | ||
import React from 'react'; | ||
|
||
import HighlightText from './HighlightText'; | ||
|
||
export default { | ||
title: 'Components/Editor/MethodConfigurationEditor/HighlightText', | ||
component: HighlightText, | ||
}; | ||
|
||
const Template = (args) => <HighlightText {...args} />; | ||
|
||
export const Default = Template.bind({}); | ||
Default.args = { | ||
value: 'Hello World!', | ||
}; | ||
|
||
export const Blue = Template.bind({}); | ||
Blue.args = { | ||
value: 'Hello World!', | ||
theme: 'blue', | ||
}; | ||
|
||
export const Yellow = Template.bind({}); | ||
Yellow.args = { | ||
value: 'Hello World!', | ||
theme: 'yellow', | ||
}; | ||
|
||
export const Green = Template.bind({}); | ||
Green.args = { | ||
value: 'Hello World!', | ||
theme: 'green', | ||
}; |
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
116 changes: 116 additions & 0 deletions
116
...gurationserver-ui/src/components/editor/method-configuration-editor/ScopeMethodDisplay.js
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,116 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import HighlightText from './HighlightText'; | ||
import _ from 'lodash'; | ||
import { MATCHER_MODE_DESCRIPTION, DEFAULT_VISIBILITIES } from './constants'; | ||
|
||
/** | ||
* Utility function for finding (case-insensitive) a specific attribute of a given object. | ||
* | ||
* @param {*} object the object being searched | ||
* @param {*} findKey the name of the attribute to find | ||
*/ | ||
const findIgnoreCase = (object, findKey) => { | ||
return _.find(object, (_value, key) => { | ||
return key.toLowerCase() === findKey; | ||
}); | ||
}; | ||
|
||
/** | ||
* Component for displaying the method matchers of given scope in a nice representation. | ||
*/ | ||
const ScopeMethodDisplay = ({ scope }) => { | ||
const { methods } = scope; | ||
|
||
// In case no method matcher exists, all methods will be used. | ||
if (!methods || methods.length === 0) { | ||
return <span className="p-component">All existing methods</span>; | ||
} | ||
|
||
// The editor does not support scopes targeting multiple methods. | ||
// Individual scopes must be used for this purpose. | ||
if (methods.length !== 1) { | ||
throw new Error('Multi-method scopes are currently not supported.'); | ||
} | ||
|
||
// the method matcher which will be shown | ||
const method = methods[0]; | ||
|
||
// defining the visual elements for the matcher's type and name | ||
let methodTypeDescriptor; | ||
let nameDescriptor; | ||
const constructor = findIgnoreCase(method, 'is-constructor'); | ||
if (constructor) { | ||
// in case constructors should be matched | ||
methodTypeDescriptor = <>Constructors</>; | ||
// nameDescriptor not needed for constructors | ||
} else { | ||
// in case methods should be matched | ||
methodTypeDescriptor = <>Methods</>; | ||
// show name only if defined | ||
const name = findIgnoreCase(method, 'name'); | ||
if (name) { | ||
const matcherMode = findIgnoreCase(method, 'matcher-mode'); | ||
const matcherText = _.get(MATCHER_MODE_DESCRIPTION, matcherMode, MATCHER_MODE_DESCRIPTION.EQUALS_FULLY); | ||
|
||
nameDescriptor = ( | ||
<> | ||
whose names <HighlightText value={matcherText} theme="blue" /> <HighlightText value={name} /> | ||
</> | ||
); | ||
} | ||
} | ||
|
||
// defining the visual elements for the matcher's visibility | ||
let visibilityDescriptor; | ||
const visibility = findIgnoreCase(method, 'visibility'); | ||
// show visibility only if defined | ||
if (!_.isEmpty(visibility)) { | ||
const isDefaultVisibility = _.isEmpty(_.difference(DEFAULT_VISIBILITIES, visibility)); | ||
|
||
// show visibility only when it differs from the default values | ||
if (!isDefaultVisibility) { | ||
const visibilities = _.join(visibility, ' OR '); | ||
visibilityDescriptor = ( | ||
<> | ||
with visibilities of <HighlightText value={visibilities} theme="green" /> | ||
</> | ||
); | ||
} | ||
} | ||
|
||
// defining the visual elements for the matcher's arguments | ||
let argumentDescriptor; | ||
const methodArguments = findIgnoreCase(method, 'arguments'); | ||
if (_.isNil(methodArguments)) { | ||
// show nothing when it is not defined | ||
} else if (_.isEmpty(methodArguments)) { | ||
// in case an empty array is specified | ||
argumentDescriptor = <>without arguments</>; | ||
} else { | ||
// in case arguments are specified - join them together | ||
const argumentsString = _.join(methodArguments, ', '); | ||
argumentDescriptor = ( | ||
<> | ||
with arguments <HighlightText value={argumentsString} theme="yellow" /> | ||
</> | ||
); | ||
} | ||
|
||
return ( | ||
<span className="p-component"> | ||
{methodTypeDescriptor} {nameDescriptor} {visibilityDescriptor} {argumentDescriptor} | ||
</span> | ||
); | ||
}; | ||
|
||
ScopeMethodDisplay.propTypes = { | ||
/** The scopes to visualize. */ | ||
scope: PropTypes.object, | ||
}; | ||
|
||
ScopeMethodDisplay.defaultProps = { | ||
scope: {}, | ||
}; | ||
|
||
export default ScopeMethodDisplay; |
71 changes: 71 additions & 0 deletions
71
...server-ui/src/components/editor/method-configuration-editor/ScopeMethodDisplay.stories.js
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,71 @@ | ||
import React from 'react'; | ||
|
||
import ScopeMethodDisplay from './ScopeMethodDisplay'; | ||
|
||
export default { | ||
title: 'Components/Editor/MethodConfigurationEditor/ScopeMethodDisplay', | ||
component: ScopeMethodDisplay, | ||
}; | ||
|
||
const Template = (args) => <ScopeMethodDisplay {...args} />; | ||
|
||
export const AllMethods = Template.bind({}); | ||
AllMethods.args = { | ||
scope: { superclass: { name: 'java.net.HttpURLConnection', 'MATCHER-MODE': 'ENDS_WITH_IGNORE_CASE' }, methods: [] }, | ||
}; | ||
|
||
export const OnlyName = Template.bind({}); | ||
OnlyName.args = { | ||
scope: { | ||
superclass: { name: 'java.net.HttpURLConnection', 'MATCHER-MODE': 'ENDS_WITH_IGNORE_CASE' }, | ||
methods: [{ name: 'getInputStream' }], | ||
}, | ||
}; | ||
|
||
export const NameMatches = Template.bind({}); | ||
NameMatches.args = { | ||
scope: { | ||
type: { name: 'org.apache.http.impl.client.CloseableHttpClient', 'Matcher-Mode': 'MATCHES' }, | ||
methods: [{ name: 'getInputStream', 'Matcher-Mode': 'STARTS_WITH_IGNORE_CASE' }], | ||
}, | ||
}; | ||
|
||
export const ByVisibility = Template.bind({}); | ||
ByVisibility.args = { | ||
scope: { | ||
interfaces: [{ name: 'org.apache.http.impl.client.CloseableHttpClient' }], | ||
methods: [{ visibility: ['PUBLIC', 'PRIVATE'] }], | ||
}, | ||
}; | ||
|
||
export const AllVisibilities = Template.bind({}); | ||
AllVisibilities.args = { | ||
scope: { | ||
interfaces: [{ name: 'org.apache.http.impl.client.CloseableHttpClient' }], | ||
methods: [{ name: 'getInputStream', visibility: ['PUBLIC', 'PRIVATE', 'PROTECTED', 'PACKAGE'] }], | ||
}, | ||
}; | ||
|
||
export const WithArguments = Template.bind({}); | ||
WithArguments.args = { | ||
scope: { | ||
interfaces: [{ name: 'org.apache.http.impl.client.CloseableHttpClient' }], | ||
methods: [{ name: 'getInputStream', arguments: ['java.lang.Object', 'java.lang.Object'] }], | ||
}, | ||
}; | ||
|
||
export const WithoutArguments = Template.bind({}); | ||
WithoutArguments.args = { | ||
scope: { | ||
interfaces: [{ name: 'org.apache.http.impl.client.CloseableHttpClient' }], | ||
methods: [{ name: 'getInputStream', arguments: [] }], | ||
}, | ||
}; | ||
|
||
export const IsConstructor = Template.bind({}); | ||
IsConstructor.args = { | ||
scope: { | ||
interfaces: [{ name: 'org.apache.http.impl.client.CloseableHttpClient' }], | ||
methods: [{ 'is-constructor': true, arguments: [], visibility: ['PUBLIC'] }], | ||
}, | ||
}; |
Oops, something went wrong.