diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2018-03-27 11:52:20 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-05-16 20:20:46 +0200 |
commit | 965717195e58808778753edd0daa0e3d9e831cdd (patch) | |
tree | f1aaeebba925cec8366fae5eccfa1f1f08fc11d6 /server/sonar-web/src/main/js | |
parent | 5073eb0f98e99ab0efbdd3f34b07a97f11e1d26c (diff) | |
download | sonarqube-965717195e58808778753edd0daa0e3d9e831cdd.tar.gz sonarqube-965717195e58808778753edd0daa0e3d9e831cdd.zip |
Introduce Bitbucket Cloud Application
SONAR-10514 Bitbucket Cloud application install/uninstall
* Bitbucket Cloud /install WS
* Expose Bitbucket application descriptor as WS
* Implement WS /integration/bitbucketcloud/uninstall
SONAR-10517 Bitbucket Cloud settings widget
* Create Bitbucket Cloud module
* Create Bitbucket Setting widget
* Bitbucket settings widget require SC authentication
* Add WS /integration/bitbucketcloud/repo_config
* Add WS /integration/bitbucketcloud/bind_repo
* Add WS /integration/bitbucketcloud/after_login
SONAR-10516 Bitbucket Cloud repository widget
* Add WS /integration/bitbucketcloud/repo_widget
* Add WS /integration/bitbucketcloud/repo_widget_data
BRANCH-59, BRANCH-60 Bitbucket Cloud PR decoration
SONAR-10605 Bitbucket Cloud PR widget
* Add integration/bitbucketcloud/pr_widget endpoint
* Add integration/bitbucketcloud/pr_widget_data endpoint
Diffstat (limited to 'server/sonar-web/src/main/js')
15 files changed, 125 insertions, 141 deletions
diff --git a/server/sonar-web/src/main/js/api/components.ts b/server/sonar-web/src/main/js/api/components.ts index 78e2b72d96a..3d7504db32f 100644 --- a/server/sonar-web/src/main/js/api/components.ts +++ b/server/sonar-web/src/main/js/api/components.ts @@ -19,7 +19,7 @@ */ import { getJSON, postJSON, post, RequestData } from '../helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; -import { Paging, Visibility, BranchParameters } from '../app/types'; +import { Paging, Visibility, BranchParameters, MyProject } from '../app/types'; export interface BaseSearchProjectsParameters { analyzedBefore?: string; @@ -145,9 +145,11 @@ export function getComponentData(data: { component: string } & BranchParameters) return getComponentShow(data).then(r => r.component); } -export function getMyProjects(data: RequestData): Promise<any> { - const url = '/api/projects/search_my_projects'; - return getJSON(url, data); +export function getMyProjects(data: { + p?: number; + ps?: number; +}): Promise<{ paging: Paging; projects: MyProject[] }> { + return getJSON('/api/projects/search_my_projects', data); } export interface Component { diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index 8fa11ed7fb1..1967bb2497e 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -312,6 +312,19 @@ export interface Metric { type: string; } +export interface MyProject { + description?: string; + key: string; + lastAnalysisDate?: string; + links: Array<{ + name: string; + type: string; + href: string; + }>; + name: string; + qualityGate?: string; +} + export interface Notification { channel: string; organization?: string; diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.js b/server/sonar-web/src/main/js/app/utils/startReactApp.js index 1b0d9750a00..a013773e344 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.js +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.js @@ -41,6 +41,7 @@ import GlobalPageExtension from '../components/extensions/GlobalPageExtension'; import GlobalAdminPageExtension from '../components/extensions/GlobalAdminPageExtension'; import MarkdownHelp from '../components/MarkdownHelp'; import NotFound from '../components/NotFound'; +import OnboardingPage from '../../apps/tutorials/onboarding/OnboardingPage'; import aboutRoutes from '../../apps/about/routes'; import accountRoutes from '../../apps/account/routes'; import backgroundTasksRoutes from '../../apps/background-tasks/routes'; @@ -179,6 +180,7 @@ const startReactApp = () => { </Route> <Route path="extension/:pluginKey/:extensionKey" component={GlobalPageExtension} /> <Route path="issues" component={IssuesPageSelector} /> + <Route path="onboarding" component={OnboardingPage} /> <Route path="organizations" childRoutes={organizationsRoutes} /> <Route path="projects" childRoutes={projectsRoutes} /> <Route path="quality_gates" childRoutes={qualityGatesRoutes} /> diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx index 15d180785b7..f05af84c229 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.tsx @@ -20,29 +20,29 @@ import * as React from 'react'; import { sortBy } from 'lodash'; import { Link } from 'react-router'; -import { Project } from './types'; import DateFromNow from '../../../components/intl/DateFromNow'; import DateTimeFormatter from '../../../components/intl/DateTimeFormatter'; import Level from '../../../components/ui/Level'; import Tooltip from '../../../components/controls/Tooltip'; import { translateWithParameters, translate } from '../../../helpers/l10n'; +import { MyProject } from '../../../app/types'; interface Props { - project: Project; + project: MyProject; } export default function ProjectCard({ project }: Props) { - const isAnalyzed = project.lastAnalysisDate != null; const links = sortBy(project.links, 'type'); + const { lastAnalysisDate } = project; return ( <div className="account-project-card clearfix"> <aside className="account-project-side"> - {isAnalyzed ? ( + {lastAnalysisDate !== undefined ? ( <div className="account-project-analysis"> - <DateFromNow date={project.lastAnalysisDate}> + <DateFromNow date={lastAnalysisDate}> {fromNow => ( - <Tooltip overlay={<DateTimeFormatter date={project.lastAnalysisDate} />}> + <Tooltip overlay={<DateTimeFormatter date={lastAnalysisDate} />}> <span>{translateWithParameters('my_account.projects.analyzed_x', fromNow)}</span> </Tooltip> )} @@ -54,7 +54,7 @@ export default function ProjectCard({ project }: Props) { </div> )} - {project.qualityGate != null && ( + {project.qualityGate !== undefined && ( <div className="account-project-quality-gate"> <Level level={project.qualityGate} /> </div> @@ -73,9 +73,9 @@ export default function ProjectCard({ project }: Props) { <a className="link-with-icon" href={link.href} - title={link.name} + rel="nofollow" target="_blank" - rel="nofollow"> + title={link.name}> <i className={`icon-color-link icon-${link.type}`} /> </a> </li> diff --git a/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx b/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx index ba029ffc813..15a00318c4b 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx +++ b/server/sonar-web/src/main/js/apps/account/projects/Projects.tsx @@ -19,15 +19,14 @@ */ import * as React from 'react'; import ProjectCard from './ProjectCard'; -import { Project } from './types'; import ListFooter from '../../../components/controls/ListFooter'; import { translate } from '../../../helpers/l10n'; +import { MyProject } from '../../../app/types'; interface Props { loading: boolean; loadMore: () => void; - projects: Project[]; - search: (query: string) => void; + projects: MyProject[]; total?: number; } @@ -55,9 +54,9 @@ export default function Projects(props: Props) { {projects.length > 0 && ( <ListFooter count={projects.length} - total={props.total || 0} - ready={!props.loading} loadMore={props.loadMore} + ready={!props.loading} + total={props.total || 0} /> )} </div> diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx index 923c7c9acb8..a5d62ac64a3 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.tsx @@ -22,22 +22,18 @@ import Helmet from 'react-helmet'; import Projects from './Projects'; import { getMyProjects } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; +import { MyProject } from '../../../app/types'; interface State { loading: boolean; page: number; - projects?: any[]; - query: string; + projects?: MyProject[]; total?: number; } export default class ProjectsContainer extends React.PureComponent<{}, State> { mounted = false; - state: State = { - loading: true, - page: 1, - query: '' - }; + state: State = { loading: true, page: 1 }; componentDidMount() { this.mounted = true; @@ -48,30 +44,22 @@ export default class ProjectsContainer extends React.PureComponent<{}, State> { this.mounted = false; } - loadProjects(page = this.state.page, query = this.state.query) { + loadProjects(page = this.state.page) { this.setState({ loading: true }); - const data: { [p: string]: any } = { ps: 100 }; - if (page > 1) { - data.p = page; - } - if (query) { - data.q = query; - } - return getMyProjects(data).then((r: any) => { - const projects = page > 1 ? [...(this.state.projects || []), ...r.projects] : r.projects; - this.setState({ - projects, - query, + const data = { p: page, ps: 100 }; + return getMyProjects(data).then(({ paging, projects }) => { + this.setState(state => ({ + projects: page > 1 ? [...(state.projects || []), ...projects] : projects, loading: false, - page: r.paging.pageIndex, - total: r.paging.total - }); + page: paging.pageIndex, + total: paging.total + })); }); } - loadMore = () => this.loadProjects(this.state.page + 1); - - search = (query: string) => this.loadProjects(1, query); + loadMore = () => { + this.loadProjects(this.state.page + 1); + }; render() { const helmet = <Helmet title={translate('my_account.projects')} />; @@ -89,11 +77,10 @@ export default class ProjectsContainer extends React.PureComponent<{}, State> { <div className="account-body account-container"> {helmet} <Projects + loadMore={this.loadMore} + loading={this.state.loading} projects={this.state.projects} total={this.state.total} - loading={this.state.loading} - loadMore={this.loadMore} - search={this.search} /> </div> ); diff --git a/server/sonar-web/src/main/js/apps/account/projects/__tests__/ProjectCard-test.js b/server/sonar-web/src/main/js/apps/account/projects/__tests__/ProjectCard-test.tsx index c714da617dc..924a53f21e1 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/__tests__/ProjectCard-test.js +++ b/server/sonar-web/src/main/js/apps/account/projects/__tests__/ProjectCard-test.tsx @@ -17,13 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import { Link } from 'react-router'; import ProjectCard from '../ProjectCard'; import Level from '../../../../components/ui/Level'; -const BASE = { id: 'id', key: 'key', name: 'name', links: [] }; +const BASE = { key: 'key', links: [], name: 'name' }; it('should render key and name', () => { const project = { ...BASE }; diff --git a/server/sonar-web/src/main/js/apps/account/projects/__tests__/Projects-test.js b/server/sonar-web/src/main/js/apps/account/projects/__tests__/Projects-test.tsx index a11086a28ce..0d2cf182fad 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/__tests__/Projects-test.js +++ b/server/sonar-web/src/main/js/apps/account/projects/__tests__/Projects-test.tsx @@ -17,46 +17,29 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import Projects from '../Projects'; import ProjectCard from '../ProjectCard'; import ListFooter from '../../../../components/controls/ListFooter'; +const PROJECTS = [ + { key: 'key1', links: [], name: 'name1' }, + { key: 'key2', links: [], name: 'name2' } +]; it('should render list of ProjectCards', () => { - const projects = [ - { id: 'id1', key: 'key1', name: 'name1', links: [] }, - { id: 'id2', key: 'key2', name: 'name2', links: [] } - ]; - const output = shallow( - <Projects - projects={projects} - total={5} - loading={false} - search={() => true} - loadMore={() => true} - /> + <Projects loadMore={() => true} loading={false} projects={PROJECTS} total={5} /> ); expect(output.find(ProjectCard).length).toBe(2); }); it('should render ListFooter', () => { - const projects = [ - { id: 'id1', key: 'key1', name: 'name1', links: [] }, - { id: 'id2', key: 'key2', name: 'name2', links: [] } - ]; const loadMore = jest.fn(); const footer = shallow( - <Projects - projects={projects} - total={5} - loading={false} - search={() => true} - loadMore={loadMore} - /> + <Projects loadMore={loadMore} loading={false} projects={PROJECTS} total={5} /> ).find(ListFooter); expect(footer.length).toBe(1); @@ -67,7 +50,7 @@ it('should render ListFooter', () => { it('should render when no results', () => { const output = shallow( - <Projects projects={[]} total={0} loading={false} search={() => true} loadMore={() => true} /> + <Projects loadMore={() => true} loading={false} projects={[]} total={0} /> ); expect(output.find('.js-no-results').length).toBe(1); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js index 2b7e5f2bca5..e7c31f647cc 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/Onboarding.js @@ -34,10 +34,10 @@ import './styles.css'; /*:: type Props = {| + className?: string, currentUser: { login: string, isLoggedIn: boolean }, onFinish: () => void, - organizationsEnabled: boolean, - sonarCloud: boolean + organizationsEnabled: boolean |}; */ @@ -58,6 +58,7 @@ export default class Onboarding extends React.PureComponent { /*:: state: State; */ static contextTypes = { + onSonarCloud: PropTypes.bool, router: PropTypes.object }; @@ -144,13 +145,13 @@ export default class Onboarding extends React.PureComponent { return null; } - const { organizationsEnabled, sonarCloud } = this.props; + const { onSonarCloud } = this.context; + const { organizationsEnabled } = this.props; const { step, token } = this.state; - let stepNumber = 1; return ( - <div className="modal-container"> + <div className={this.props.className}> <InstanceMessage message={translate('onboarding.header')}> {transformedMessage => <Helmet title={transformedMessage} titleTemplate="%s" />} </InstanceMessage> @@ -170,7 +171,7 @@ export default class Onboarding extends React.PureComponent { )} <p className="note"> {translate( - sonarCloud ? 'tutorials.find_it_back_in_plus' : 'tutorials.find_it_back_in_help' + onSonarCloud ? 'tutorials.find_it_back_in_plus' : 'tutorials.find_it_back_in_help' )} </p> </div> @@ -205,9 +206,9 @@ export default class Onboarding extends React.PureComponent { <AnalysisStep onFinish={this.handleFinish} onReset={this.handleReset} - organization={this.state.organization} open={step === 'analysis'} - sonarCloud={sonarCloud} + organization={this.state.organization} + sonarCloud={onSonarCloud} stepNumber={stepNumber} token={token} /> diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js index 18cc38d1f5c..cf27d5dd333 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingContainer.js @@ -20,19 +20,13 @@ // @flow import { connect } from 'react-redux'; import Onboarding from './Onboarding'; -import { - getCurrentUser, - areThereCustomOrganizations, - getGlobalSettingValue -} from '../../../store/rootReducer'; +import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer'; const mapStateToProps = state => { - const sonarCloudSetting = getGlobalSettingValue(state, 'sonar.sonarcloud.enabled'); - return { + className: 'modal-container', currentUser: getCurrentUser(state), - organizationsEnabled: areThereCustomOrganizations(state), - sonarCloud: sonarCloudSetting != null && sonarCloudSetting.value === 'true' + organizationsEnabled: areThereCustomOrganizations(state) }; }; diff --git a/server/sonar-web/src/main/js/apps/account/projects/types.ts b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingPage.tsx index 930334bea55..971ae8bddff 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/types.ts +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/OnboardingPage.tsx @@ -17,16 +17,31 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -export interface Project { - id: string; - key: string; - name: string; - lastAnalysisDate: string; - description: string; - links: Array<{ - href: string; - name: string; - type: string; - }>; - qualityGate: string; +import * as React from 'react'; +import * as PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import OnboardingModal from './OnboardingModal'; +import { skipOnboarding } from '../../../store/users/actions'; + +interface DispatchProps { + skipOnboarding: () => void; } + +export class OnboardingPage extends React.PureComponent<DispatchProps> { + static contextTypes = { + router: PropTypes.object.isRequired + }; + + onSkipOnboardingTutorial = () => { + this.props.skipOnboarding(); + this.context.router.replace('/'); + }; + + render() { + return <OnboardingModal onFinish={this.onSkipOnboardingTutorial} />; + } +} + +const mapDispatchToProps: DispatchProps = { skipOnboarding }; + +export default connect<{}, DispatchProps, {}>(null, mapDispatchToProps)(OnboardingPage); diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js index 4d66e667374..2d5019ae82d 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/Onboarding-test.js @@ -32,10 +32,10 @@ const currentUser = { login: 'admin', isLoggedIn: true }; it('guides for on-premise', () => { const wrapper = shallow( <Onboarding + className="modal-container" currentUser={currentUser} onFinish={jest.fn()} organizationsEnabled={false} - sonarCloud={false} /> ); expect(wrapper).toMatchSnapshot(); @@ -48,12 +48,8 @@ it('guides for on-premise', () => { it('guides for sonarcloud', () => { const wrapper = shallow( - <Onboarding - currentUser={currentUser} - onFinish={jest.fn()} - organizationsEnabled={true} - sonarCloud={true} - /> + <Onboarding currentUser={currentUser} onFinish={jest.fn()} organizationsEnabled={true} />, + { context: { onSonarCloud: true } } ); expect(wrapper).toMatchSnapshot(); @@ -71,12 +67,7 @@ it('guides for sonarcloud', () => { it('finishes', () => { const onFinish = jest.fn(); const wrapper = mount( - <Onboarding - currentUser={currentUser} - onFinish={onFinish} - organizationsEnabled={false} - sonarCloud={false} - /> + <Onboarding currentUser={currentUser} onFinish={onFinish} organizationsEnabled={false} /> ); click(wrapper.find('.js-skip')); return doAsync(() => { diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap index 373e5949514..997502681fe 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/Onboarding-test.js.snap @@ -59,7 +59,6 @@ exports[`guides for on-premise 1`] = ` onFinish={[Function]} onReset={[Function]} open={false} - sonarCloud={false} stepNumber={2} /> </div> @@ -125,7 +124,6 @@ exports[`guides for on-premise 2`] = ` onFinish={[Function]} onReset={[Function]} open={true} - sonarCloud={false} stepNumber={2} token="abcd1234" /> @@ -134,9 +132,7 @@ exports[`guides for on-premise 2`] = ` `; exports[`guides for sonarcloud 1`] = ` -<div - className="modal-container" -> +<div> <InstanceMessage message="onboarding.header" /> @@ -213,9 +209,7 @@ exports[`guides for sonarcloud 1`] = ` `; exports[`guides for sonarcloud 2`] = ` -<div - className="modal-container" -> +<div> <InstanceMessage message="onboarding.header" /> @@ -293,9 +287,7 @@ exports[`guides for sonarcloud 2`] = ` `; exports[`guides for sonarcloud 3`] = ` -<div - className="modal-container" -> +<div> <InstanceMessage message="onboarding.header" /> diff --git a/server/sonar-web/src/main/js/components/common/BranchStatus.tsx b/server/sonar-web/src/main/js/components/common/BranchStatus.tsx index 1738e5c1fa1..2fc23b47849 100644 --- a/server/sonar-web/src/main/js/components/common/BranchStatus.tsx +++ b/server/sonar-web/src/main/js/components/common/BranchStatus.tsx @@ -26,7 +26,12 @@ import HelpTooltip from '../controls/HelpTooltip'; import Tooltip from '../controls/Tooltip'; import VulnerabilityIcon from '../icons-components/VulnerabilityIcon'; import { BranchLike } from '../../app/types'; -import { isShortLivingBranch, isPullRequest, isLongLivingBranch } from '../../helpers/branches'; +import { + getBranchQualityGateColor, + isShortLivingBranch, + isPullRequest, + isLongLivingBranch +} from '../../helpers/branches'; import { translateWithParameters } from '../../helpers/l10n'; import { formatMeasure } from '../../helpers/measures'; import './BranchStatus.css'; @@ -45,7 +50,7 @@ export default function BranchStatus({ branchLike, concise = false }: Props) { const totalIssues = branchLike.status.bugs + branchLike.status.vulnerabilities + branchLike.status.codeSmells; const status = branchLike.status.qualityGateStatus; - const indicatorColor = getQualityGateColor(status); + const indicatorColor = getBranchQualityGateColor(status); const shouldDisplayHelper = status === 'OK' && totalIssues > 0; const label = @@ -102,15 +107,3 @@ export default function BranchStatus({ branchLike, concise = false }: Props) { return null; } } - -function getQualityGateColor(status: string) { - let indicatorColor = 'gray'; - if (status === 'ERROR') { - indicatorColor = 'red'; - } else if (status === 'WARN') { - indicatorColor = 'orange'; - } else if (status === 'OK') { - indicatorColor = 'green'; - } - return indicatorColor; -} diff --git a/server/sonar-web/src/main/js/helpers/branches.ts b/server/sonar-web/src/main/js/helpers/branches.ts index cb930b0a80b..6b4507eddcd 100644 --- a/server/sonar-web/src/main/js/helpers/branches.ts +++ b/server/sonar-web/src/main/js/helpers/branches.ts @@ -69,6 +69,18 @@ export function getBranchLikeKey(branchLike: BranchLike) { return isPullRequest(branchLike) ? `pull-request-${branchLike.key}` : `branch-${branchLike.name}`; } +export function getBranchQualityGateColor(status: string) { + let indicatorColor = 'gray'; + if (status === 'ERROR') { + indicatorColor = 'red'; + } else if (status === 'WARN') { + indicatorColor = 'orange'; + } else if (status === 'OK') { + indicatorColor = 'green'; + } + return indicatorColor; +} + export function isSameBranchLike(a: BranchLike | undefined, b: BranchLike | undefined) { // main branches are always equal if (isMainBranch(a) && isMainBranch(b)) { |