+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * 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 { Link } from 'react-router';
-import SimpleContainer from './SimpleContainer';
-
-/*::
-type Props = {
- withContainer?: boolean;
-};
-*/
-
-export default function NotFound({ withContainer = true } /*: Props*/) {
- const Container = withContainer ? SimpleContainer : React.Fragment;
- return (
- <Container>
- <div className="page-wrapper-simple" id="bd">
- <div className="page-simple" id="nonav">
- <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2>
- <p className="spacer-bottom">
- You may have mistyped the address or the page may have moved.
- </p>
- <p>
- <Link to="/">Go back to the homepage</Link>
- </p>
- </div>
- </div>
- </Container>
- );
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { Link } from 'react-router';
+import SimpleContainer from './SimpleContainer';
+
+interface Props {
+ withContainer?: boolean;
+}
+
+export default function NotFound({ withContainer = true }: Props) {
+ const Container = withContainer ? SimpleContainer : React.Fragment;
+ return (
+ <Container>
+ <div className="page-wrapper-simple" id="bd">
+ <div className="page-simple" id="nonav">
+ <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2>
+ <p className="spacer-bottom">
+ You may have mistyped the address or the page may have moved.
+ </p>
+ <p>
+ <Link to="/">Go back to the homepage</Link>
+ </p>
+ </div>
+ </div>
+ </Container>
+ );
+}
import * as React from 'react';
import { connect } from 'react-redux';
import { RouterState } from 'react-router';
-import {
- getCurrentUser,
- getMyOrganizations,
- getOrganizationByKey
-} from '../../../store/rootReducer';
+import { getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer';
import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization';
import { Organization, CurrentUser, isLoggedIn } from '../../../app/types';
-import { isCurrentUserMemberOf, hasPrivateAccess } from '../../../helpers/organizations';
-import {} from '../../../store/organizations/duck';
interface StateToProps {
currentUser: CurrentUser;
organization?: Organization;
- userOrganizations: Organization[];
}
interface OwnProps extends RouterState {
const mapStateToProps = (state: any, ownProps: OwnProps) => ({
currentUser: getCurrentUser(state),
- organization: getOrganizationByKey(state, ownProps.params.organizationKey),
- userOrganizations: getMyOrganizations(state)
+ organization: getOrganizationByKey(state, ownProps.params.organizationKey)
});
const OrganizationAccessContainer = connect<StateToProps, {}, OwnProps>(mapStateToProps)(
OrganizationAccess
);
-export function OrganizationPrivateAccess(props: OwnProps) {
- return (
- <OrganizationAccessContainer
- hasAccess={({ currentUser, organization, userOrganizations }: StateToProps) =>
- hasPrivateAccess(currentUser, organization, userOrganizations)
- }
- {...props}
- />
- );
-}
-
-export function OrganizationMembersAccess(props: OwnProps) {
- return (
- <OrganizationAccessContainer
- hasAccess={({ currentUser, organization, userOrganizations }: StateToProps) =>
- isCurrentUserMemberOf(currentUser, organization, userOrganizations)
- }
- {...props}
- />
- );
-}
-
export function hasAdminAccess({
currentUser,
organization
isDestructive={true}
modalBody={
<div>
- {translate('organization.delete.question')}
{hasPaidPlan && (
- <p className="alert alert-warn big-spacer-top">
+ <div className="alert alert-warning modal-alert">
{translate('organization.delete.sonarcloud.paid_plan_info')}
- </p>
+ </div>
)}
+ <p>{translate('organization.delete.question')}</p>
</div>
}
modalHeader={translate('organization.delete')}
if (this.state.loading) {
return null;
} else {
- return <NotFound />;
+ return <NotFound withContainer={false} />;
}
}
currentUser={loggedInUser}
hasAccess={() => true}
location={locationMock}
- organization={adminOrganization}
- userOrganizations={[]}>
+ organization={adminOrganization}>
<div>hello</div>
</OrganizationAccess>
)
currentUser={loggedInUser}
hasAccess={() => false}
location={locationMock}
- organization={adminOrganization}
- userOrganizations={[]}>
+ organization={adminOrganization}>
<div>hello</div>
</OrganizationAccess>
).type()
isDestructive={true}
modalBody={
<div>
- organization.delete.question
- <p
- className="alert alert-warn big-spacer-top"
+ <div
+ className="alert alert-warning modal-alert"
>
organization.delete.sonarcloud.paid_plan_info
+ </div>
+ <p>
+ organization.delete.question
</p>
</div>
}
isDestructive={true}
modalBody={
<div>
- organization.delete.question
+ <p>
+ organization.delete.question
+ </p>
</div>
}
modalHeader="organization.delete"
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`not found 1`] = `<NotFound />`;
+exports[`not found 1`] = `
+<NotFound
+ withContainer={false}
+/>
+`;
exports[`should correctly update when the organization changes 1`] = `
Array [
childRoutes: codingRulesRoutes
},
{
- component: lazyLoad(() =>
- import('./components/OrganizationAccessContainer').then(lib => ({
- default: lib.OrganizationMembersAccess
- }))
- ),
- childRoutes: [
- {
- path: 'members',
- component: lazyLoad(() => import('./components/OrganizationMembersContainer'))
- }
- ]
+ path: 'members',
+ component: lazyLoad(() => import('./components/OrganizationMembersContainer'))
},
{
- component: lazyLoad(() =>
- import('./components/OrganizationAccessContainer').then(lib => ({
- default: lib.OrganizationPrivateAccess
- }))
- ),
- childRoutes: [
- {
- path: 'quality_profiles',
- childRoutes: qualityProfilesRoutes
- },
- {
- path: 'quality_gates',
- component: OrganizationContainer,
- childRoutes: qualityGatesRoutes
- }
- ]
+ path: 'quality_profiles',
+ childRoutes: qualityProfilesRoutes
+ },
+ {
+ path: 'quality_gates',
+ component: OrganizationContainer,
+ childRoutes: qualityGatesRoutes
},
{
component: lazyLoad(() =>
return React.cloneElement(this.props.children, {
actions: this.state.actions || {},
- profiles: this.state.profiles,
+ profiles: this.state.profiles || [],
languages: finalLanguages,
exporters: this.state.exporters,
updateProfiles: this.updateProfiles,
import { getRulesUrl } from '../../../helpers/urls';
import { toShortNotSoISOString } from '../../../helpers/dates';
import { formatMeasure } from '../../../helpers/measures';
+import { Rule, RuleActivation } from '../../../app/types';
const RULES_LIMIT = 10;
-function parseRules(r: any) {
- const { rules, actives } = r;
- return rules.map((rule: any) => {
- const activations = actives[rule.key];
+function parseRules(rules: Rule[], actives?: { [rule: string]: RuleActivation[] }): ExtendedRule[] {
+ return rules.map(rule => {
+ const activations = actives && actives[rule.key];
return { ...rule, activations: activations ? activations.length : 0 };
});
}
organization: string | null;
}
-interface Rule {
+interface ExtendedRule extends Rule {
activations: number;
- key: string;
- langName: string;
- name: string;
}
interface State {
- latestRules?: Array<Rule>;
+ latestRules?: ExtendedRule[];
latestRulesTotal?: number;
}
};
searchRules(data).then(
- (r: any) => {
+ ({ actives, rules, total }) => {
if (this.mounted) {
this.setState({
- latestRules: sortBy<Rule>(parseRules(r), 'langName'),
- latestRulesTotal: r.total
+ latestRules: sortBy(parseRules(rules, actives), 'langName'),
+ latestRulesTotal: total
});
}
},
</div>
<ul>
{this.state.latestRules.map(rule => (
- <li key={rule.key} className="spacer-top">
+ <li className="spacer-top" key={rule.key}>
<div className="text-ellipsis">
<Link
- to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}
- className="link-no-underline">
+ className="link-no-underline"
+ to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}>
{' '}
{rule.name}
</Link>
</ul>
{this.state.latestRulesTotal > RULES_LIMIT && (
<div className="spacer-top">
- <Link to={newRulesUrl} className="small">
+ <Link className="small" to={newRulesUrl}>
{translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)}
</Link>
</div>
location: { query: { [p: string]: string } };
onRequestFail: (reason: any) => void;
organization: string | null;
- profiles: Array<Profile>;
+ profiles: Profile[];
updateProfiles: () => Promise<void>;
}