aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-01-26 14:34:51 +0100
committerStas Vilchik <vilchiks@gmail.com>2016-01-28 16:14:24 +0100
commitde0b07fffd01cc2552c9a4a50ebbc994fb684400 (patch)
treec66be7f9c8ae4761ef7b4cc64f96f7e51cd954b4
parent2a981676b2f034933c01b7fd7b745a61263690ac (diff)
downloadsonarqube-de0b07fffd01cc2552c9a4a50ebbc994fb684400.tar.gz
sonarqube-de0b07fffd01cc2552c9a4a50ebbc994fb684400.zip
SONAR-7230 Move user notifications into separate page of "My Account" space
-rw-r--r--it/it-tests/src/test/java/it/qualityGate/QualityGateNotificationTest.java1
-rw-r--r--it/it-tests/src/test/resources/qualityGate/notifications/activate_notification_channels.html11
-rw-r--r--server/sonar-web/src/main/js/api/components.js10
-rw-r--r--server/sonar-web/src/main/js/apps/account/app.js21
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/GlobalNotifications.js53
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/Nav.js5
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/Notifications.js41
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/NotificationsList.js42
-rw-r--r--server/sonar-web/src/main/js/apps/account/components/ProjectNotifications.js102
-rw-r--r--server/sonar-web/src/main/js/apps/account/containers/NotificationsContainer.js42
-rw-r--r--server/sonar-web/src/main/js/apps/account/store/actions.js35
-rw-r--r--server/sonar-web/src/main/js/apps/account/store/configureStore.js36
-rw-r--r--server/sonar-web/src/main/js/apps/account/store/reducers.js69
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/account_controller.rb12
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb1
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb71
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/config/routes.rb2
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
18 files changed, 529 insertions, 27 deletions
diff --git a/it/it-tests/src/test/java/it/qualityGate/QualityGateNotificationTest.java b/it/it-tests/src/test/java/it/qualityGate/QualityGateNotificationTest.java
index 37271141fbe..5920d677138 100644
--- a/it/it-tests/src/test/java/it/qualityGate/QualityGateNotificationTest.java
+++ b/it/it-tests/src/test/java/it/qualityGate/QualityGateNotificationTest.java
@@ -70,7 +70,6 @@ public class QualityGateNotificationTest {
}
@Test
- @Ignore("waiting for SONAR-7230")
public void status_on_metric_variation_and_send_notifications() throws Exception {
Wiser smtpServer = new Wiser(NetworkUtils.getNextAvailablePort());
try {
diff --git a/it/it-tests/src/test/resources/qualityGate/notifications/activate_notification_channels.html b/it/it-tests/src/test/resources/qualityGate/notifications/activate_notification_channels.html
index b72649cf564..fc1b770918e 100644
--- a/it/it-tests/src/test/resources/qualityGate/notifications/activate_notification_channels.html
+++ b/it/it-tests/src/test/resources/qualityGate/notifications/activate_notification_channels.html
@@ -35,17 +35,22 @@
</tr>
<tr>
<td>open</td>
- <td>/account/index</td>
+ <td>/sonar/account/notifications</td>
+ <td></td>
+</tr>
+<tr>
+ <td>waitForElementPresent</td>
+ <td>id=global_notifs_NewAlerts_EmailNotificationChannel</td>
<td></td>
</tr>
<tr>
<td>check</td>
- <td>global_notifs_NewAlerts.EmailNotificationChannel</td>
+ <td>id=global_notifs_NewAlerts_EmailNotificationChannel</td>
<td></td>
</tr>
<tr>
<td>clickAndWait</td>
- <td>//input[@value='Save changes']</td>
+ <td>id=submit-notifications</td>
<td></td>
</tr>
</tbody>
diff --git a/server/sonar-web/src/main/js/api/components.js b/server/sonar-web/src/main/js/api/components.js
index 89a6e35ffec..32ed9f744cd 100644
--- a/server/sonar-web/src/main/js/api/components.js
+++ b/server/sonar-web/src/main/js/api/components.js
@@ -91,3 +91,13 @@ export function getBreadcrumbs ({ id, key }) {
return [...reversedAncestors, r.component];
});
}
+
+export function getProjectsWithInternalId (query) {
+ const url = window.baseUrl + '/api/resources/search';
+ const data = {
+ f: 's2',
+ q: 'TRK',
+ s: query
+ };
+ return getJSON(url, data).then(r => r.results);
+}
diff --git a/server/sonar-web/src/main/js/apps/account/app.js b/server/sonar-web/src/main/js/apps/account/app.js
index 5af38f5b6c3..4a78a6a04fb 100644
--- a/server/sonar-web/src/main/js/apps/account/app.js
+++ b/server/sonar-web/src/main/js/apps/account/app.js
@@ -21,10 +21,12 @@ import React from 'react';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, Redirect } from 'react-router';
import { createHistory, useBasename } from 'history';
+import { Provider } from 'react-redux';
+import configureStore from './store/configureStore';
import AccountApp from './containers/AccountApp';
import Home from './components/Home';
-import Notifications from './components/Notifications';
+import NotificationsContainer from './containers/NotificationsContainer';
window.sonarqube.appStarted.then(options => {
const el = document.querySelector(options.el);
@@ -33,16 +35,21 @@ window.sonarqube.appStarted.then(options => {
basename: window.baseUrl + '/account'
});
+ const store = configureStore();
+
document.querySelector('html').classList.add('dashboard-page');
document.querySelector('#container').classList.add('page-wrapper-context');
render((
- <Router history={history}>
- <Route path="/" component={AccountApp}>
- <IndexRoute component={Home}/>
+ <Provider store={store}>
+ <Router history={history}>
+ <Route path="/" component={AccountApp}>
+ <IndexRoute component={Home}/>
+ <Route path="notifications" component={NotificationsContainer}/>
- <Redirect from="/index" to="/"/>
- </Route>
- </Router>
+ <Redirect from="/index" to="/"/>
+ </Route>
+ </Router>
+ </Provider>
), el);
});
diff --git a/server/sonar-web/src/main/js/apps/account/components/GlobalNotifications.js b/server/sonar-web/src/main/js/apps/account/components/GlobalNotifications.js
new file mode 100644
index 00000000000..5f5de5de9b4
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/components/GlobalNotifications.js
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 NotificationsList from './NotificationsList';
+import { translate } from '../../../helpers/l10n';
+
+export default function GlobalNotifications ({ notifications, channels }) {
+ return (
+ <div>
+ <header className="page-header">
+ <h2 className="page-title">
+ {translate('my_profile.overall_notifications.title')}
+ </h2>
+ </header>
+
+ <table className="form">
+ <thead>
+ <tr>
+ <th></th>
+ {channels.map(channel => (
+ <th key={channel} className="text-center">
+ <h4>{translate('notification.channel', channel)}</h4>
+ </th>
+ ))}
+ </tr>
+ </thead>
+
+ <NotificationsList
+ notifications={notifications}
+ checkboxId={(d, c) => `global_notifs_${d}_${c}`}
+ checkboxName={(d, c) => `global_notifs[${d}.${c}]`}/>
+ </table>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/account/components/Nav.js b/server/sonar-web/src/main/js/apps/account/components/Nav.js
index 3a85c7da307..e19213d3062 100644
--- a/server/sonar-web/src/main/js/apps/account/components/Nav.js
+++ b/server/sonar-web/src/main/js/apps/account/components/Nav.js
@@ -38,6 +38,11 @@ const Nav = () => (
<i className="icon-home"/>
</IndexLink>
</li>
+ <li>
+ <IndexLink to="notifications" activeClassName="active">
+ {translate('my_account.notifications')}
+ </IndexLink>
+ </li>
</ul>
</div>
</nav>
diff --git a/server/sonar-web/src/main/js/apps/account/components/Notifications.js b/server/sonar-web/src/main/js/apps/account/components/Notifications.js
index 195a134c15c..45a9d5839eb 100644
--- a/server/sonar-web/src/main/js/apps/account/components/Notifications.js
+++ b/server/sonar-web/src/main/js/apps/account/components/Notifications.js
@@ -19,8 +19,41 @@
*/
import React from 'react';
-const Notifications = () => (
- <h1>Notifications</h1>
-);
+import GlobalNotifications from './GlobalNotifications';
+import ProjectNotifications from './ProjectNotifications';
+import { translate } from '../../../helpers/l10n';
-export default Notifications;
+export default function Notifications ({ globalNotifications, projectNotifications, onAddProject, onRemoveProject }) {
+ const channels = globalNotifications[0].channels.map(c => c.id);
+
+ return (
+ <div>
+ <p className="big-spacer-bottom">
+ {translate('notification.dispatcher.information')}
+ </p>
+ <form id="notif_form" method="post" action={`${window.baseUrl}/account/update_notifications`}>
+ <div className="columns">
+ <div className="column-half">
+ <GlobalNotifications
+ notifications={globalNotifications}
+ channels={channels}/>
+ </div>
+
+ <div className="column-half">
+ <ProjectNotifications
+ notifications={projectNotifications}
+ channels={channels}
+ onAddProject={onAddProject}
+ onRemoveProject={onRemoveProject}/>
+ </div>
+ </div>
+
+ <p className="big-spacer-top panel panel-vertical bordered-top text-right">
+ <button id="submit-notifications" type="submit">
+ {translate('my_profile.notifications.submit')}
+ </button>
+ </p>
+ </form>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/account/components/NotificationsList.js b/server/sonar-web/src/main/js/apps/account/components/NotificationsList.js
new file mode 100644
index 00000000000..a8044b4b142
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/components/NotificationsList.js
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 { translate } from '../../../helpers/l10n';
+
+export default function NotificationsList ({ notifications, checkboxName, checkboxId }) {
+ return (
+ <tbody>
+ {notifications.map(notification => (
+ <tr key={notification.dispatcher}>
+ <td>{translate('notification.dispatcher', notification.dispatcher)}</td>
+ {notification.channels.map(channel => (
+ <td key={channel.id} className="text-center">
+ <input defaultChecked={channel.checked}
+ id={checkboxId(notification.dispatcher, channel.id)}
+ name={checkboxName(notification.dispatcher, channel.id)}
+ type="checkbox"/>
+ </td>
+ ))}
+ </tr>
+ ))}
+ </tbody>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/account/components/ProjectNotifications.js b/server/sonar-web/src/main/js/apps/account/components/ProjectNotifications.js
new file mode 100644
index 00000000000..5683e50e1d8
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/components/ProjectNotifications.js
@@ -0,0 +1,102 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 Select from 'react-select';
+
+import NotificationsList from './NotificationsList';
+import { translate } from '../../../helpers/l10n';
+import { getProjectsWithInternalId } from '../../../api/components';
+
+export default function ProjectNotifications ({ notifications, channels, onAddProject, onRemoveProject }) {
+ const loadOptions = (query) => {
+ return getProjectsWithInternalId(query)
+ .then(results => results.map(r => {
+ return {
+ value: r.id,
+ label: r.text
+ };
+ }))
+ .then(options => {
+ return { options };
+ });
+ };
+
+ const handleAddProject = (selected) => {
+ const project = {
+ internalId: selected.value,
+ name: selected.label
+ };
+ onAddProject(project);
+ };
+
+ const handleRemoveProject = (project) => (
+ (e) => {
+ e.preventDefault;
+ onRemoveProject(project);
+ }
+ );
+
+ return (
+ <div>
+ <header className="page-header">
+ <h2 className="page-title">
+ {translate('my_profile.per_project_notifications.title')}
+ </h2>
+ <div className="pull-right">
+ <Select.Async
+ name="new_project"
+ style={{ width: '150px' }}
+ loadOptions={loadOptions}
+ onChange={handleAddProject}
+ placeholder="Add Project"/>
+ </div>
+ </header>
+
+ {!notifications.length && (
+ <div className="note">
+ {translate('my_account.no_project_notifications')}
+ </div>
+ )}
+
+ {notifications.map(p => (
+ <table key={p.project.internalId} className="form spacer-bottom">
+ <thead>
+ <tr>
+ <th>
+ <a onClick={handleRemoveProject(p.project)}
+ className="spacer-right icon-delete js-delete-project" href="#"></a>
+ <h3 className="display-inline-block">{p.project.name}</h3>
+ </th>
+ {channels.map(channel => (
+ <th key={channel} className="text-center">
+ <h4>{translate('notification.channel', channel)}</h4>
+ </th>
+ ))}
+ </tr>
+ </thead>
+ <NotificationsList
+ notifications={p.notifications}
+ checkboxId={(d, c) => `project_notifs_${p.project.internalId}_${d}_${c}`}
+ checkboxName={(d, c) => `project_notifs[${p.project.internalId}][${d}][${c}]`}/>
+ </table>
+ ))}
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/account/containers/NotificationsContainer.js b/server/sonar-web/src/main/js/apps/account/containers/NotificationsContainer.js
new file mode 100644
index 00000000000..84328295905
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/containers/NotificationsContainer.js
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 { connect } from 'react-redux';
+
+import { addProjectNotifications, removeProjectNotifications } from '../store/actions';
+import Notifications from './../components/Notifications';
+
+function mapStateToProps (state) {
+ return {
+ globalNotifications: window.sonarqube.notifications.global,
+ projectNotifications: state.projectNotifications
+ };
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ onAddProject: (project) => dispatch(addProjectNotifications(project)),
+ onRemoveProject: (project) => dispatch(removeProjectNotifications(project))
+ };
+}
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(Notifications);
diff --git a/server/sonar-web/src/main/js/apps/account/store/actions.js b/server/sonar-web/src/main/js/apps/account/store/actions.js
new file mode 100644
index 00000000000..bee94192a5c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/store/actions.js
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.
+ */
+export const ADD_PROJECT_NOTIFICATIONS = 'ADD_PROJECT_NOTIFICATIONS';
+export const REMOVE_PROJECT_NOTIFICATIONS = 'REMOVE_PROJECT_NOTIFICATIONS';
+
+export function addProjectNotifications (project) {
+ return {
+ type: ADD_PROJECT_NOTIFICATIONS,
+ project
+ };
+}
+
+export function removeProjectNotifications (project) {
+ return {
+ type: REMOVE_PROJECT_NOTIFICATIONS,
+ project
+ };
+}
diff --git a/server/sonar-web/src/main/js/apps/account/store/configureStore.js b/server/sonar-web/src/main/js/apps/account/store/configureStore.js
new file mode 100644
index 00000000000..e412913dc76
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/store/configureStore.js
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 { createStore, applyMiddleware } from 'redux';
+import thunk from 'redux-thunk';
+import createLogger from 'redux-logger';
+import rootReducer from './reducers';
+
+const logger = createLogger({
+ predicate: () => process.env.NODE_ENV !== 'production'
+});
+
+const createStoreWithMiddleware = applyMiddleware(
+ thunk,
+ logger
+)(createStore);
+
+export default function configureStore () {
+ return createStoreWithMiddleware(rootReducer);
+}
diff --git a/server/sonar-web/src/main/js/apps/account/store/reducers.js b/server/sonar-web/src/main/js/apps/account/store/reducers.js
new file mode 100644
index 00000000000..23921840d8b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/account/store/reducers.js
@@ -0,0 +1,69 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 { ADD_PROJECT_NOTIFICATIONS, REMOVE_PROJECT_NOTIFICATIONS } from './actions';
+
+function addProjectNotifications (state, project) {
+ const found = state.find(notification => {
+ return notification.project.internalId === project.internalId;
+ });
+
+ if (found) {
+ return state;
+ }
+
+ const newProjectNotification = {
+ project,
+ notifications: window.sonarqube.notifications.projectDispatchers.map(dispatcher => {
+ const channels = window.sonarqube.notifications.channels.map(channel => {
+ return { id: channel, checked: false };
+ });
+ return { dispatcher, channels };
+ })
+ };
+
+ return [...state, newProjectNotification];
+}
+
+function removeProjectNotifications (state, project) {
+ return state.filter(notification => {
+ return notification.project.internalId !== project.internalId;
+ });
+}
+
+export const initialState = {
+ projectNotifications: window.sonarqube.notifications.project
+};
+
+export default function (state = initialState, action) {
+ switch (action.type) {
+ case ADD_PROJECT_NOTIFICATIONS:
+ return {
+ ...state,
+ projectNotifications: addProjectNotifications(state.projectNotifications, action.project)
+ };
+ case REMOVE_PROJECT_NOTIFICATIONS:
+ return {
+ ...state,
+ projectNotifications: removeProjectNotifications(state.projectNotifications, action.project)
+ };
+ default:
+ return state;
+ }
+}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/account_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/account_controller.rb
index aa803c1f9b9..508c5ac7ae1 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/account_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/account_controller.rb
@@ -22,10 +22,6 @@ class AccountController < ApplicationController
before_filter :login_required
def index
-
- end
-
- def notifications
@channels = notification_service.getChannels()
@global_dispatchers = dispatchers_for_scope("globalNotification")
@per_project_dispatchers = dispatchers_for_scope("perProjectNotification")
@@ -84,13 +80,7 @@ class AccountController < ApplicationController
end
end
- # New project added
- new_params = {}
- unless params[:new_project].blank?
- new_params[:new_project] = params[:new_project]
- end
-
- redirect_to :action => 'index', :params => new_params
+ redirect_to "#{ApplicationController.root_context}/account/notifications"
end
private
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb
index b85e5c7adbb..64da4002f0c 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb
@@ -39,7 +39,6 @@ class Api::ResourcesController < Api::ApiController
qualifiers=[]
end
- bad_request("Minimum search is #{ResourceIndex::MIN_SEARCH_SIZE} characters") if search_text.size<ResourceIndex::MIN_SEARCH_SIZE
bad_request("Page index must be greater than 0") if page<=0
bad_request("Page size must be greater than 0") if page_size<=0
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb
index 4ffc62880f0..f5a9a100226 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/account/index.html.erb
@@ -33,6 +33,77 @@
<% end %>
]
};
+ window.sonarqube.notifications = {
+ channels: [
+ <% for channel in @channels -%>
+ '<%= escape_javascript channel.getKey() -%>',
+ <% end %>
+ ],
+
+ globalDispatchers: [
+ <% for dispatcher in @global_dispatchers -%>
+ '<%= escape_javascript dispatcher -%>',
+ <% end %>
+ ],
+
+ projectDispatchers: [
+ <% for dispatcher in @per_project_dispatchers -%>
+ '<%= escape_javascript dispatcher -%>',
+ <% end %>
+ ],
+
+ global: [
+ <% for dispatcher in @global_dispatchers %>
+ {
+ dispatcher: '<%= escape_javascript dispatcher -%>',
+ channels: [
+ <%
+ for channel in @channels
+ notification_id = dispatcher + '.' + channel.getKey()
+ check_box_checked = @global_notifications[notification_id]
+ -%>
+ {
+ id: '<%= escape_javascript channel.getKey() -%>',
+ checked: <%= check_box_checked ? 'true' : 'false' %>
+ },
+ <% end %>
+ ]
+ },
+ <% end %>
+ ],
+
+ project: [
+ <% @per_project_notifications.each do |project_key, notification| %>
+ <% project = Project.by_key(project_key) %>
+ {
+ project: {
+ internalId: <%= project.id -%>,
+ id: '<%= escape_javascript project.uuid -%>',
+ key: '<%= escape_javascript project.key -%>',
+ name: '<%= escape_javascript project.name -%>'
+ },
+ notifications: [
+ <% @per_project_dispatchers.each do |dispatcher| %>
+ {
+ dispatcher: '<%= escape_javascript dispatcher -%>',
+ channels: [
+ <%
+ for channel in @channels
+ check_box_checked = notification[dispatcher].include?(channel.getKey())
+ -%>
+ {
+ id: '<%= escape_javascript channel.getKey() -%>',
+ checked: <%= check_box_checked ? 'true' : 'false' %>
+ },
+ <% end %>
+ ]
+ },
+ <% end %>
+ ]
+ },
+ <% end %>
+ ]
+ };
</script>
<script src="<%= ApplicationController.root_context -%>/js/bundles/account.js?v=<%= sonar_version -%>"></script>
<% end %>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/config/routes.rb b/server/sonar-web/src/main/webapp/WEB-INF/config/routes.rb
index 36e2931ee2f..69814d108fb 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/config/routes.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/config/routes.rb
@@ -34,6 +34,8 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'api_documentation/*other', :controller => 'api_documentation', :action => 'index'
map.connect 'quality_gates/*other', :controller => 'quality_gates', :action => 'index'
map.connect 'overview/*other', :controller => 'overview', :action => 'index'
+ map.connect 'account/update_notifications', :controller => 'account', :action => 'update_notifications'
+ map.connect 'account/*other', :controller => 'account', :action => 'index'
# Install the default route as the lowest priority.
map.connect ':controller/:action/:id', :requirements => { :id => /.*/ }
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index c8f3f6da8fd..fad0339a29d 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2159,6 +2159,8 @@ my_account.page=My Account
my_account.favorite_components=Favorite Components
my_account.favorite_issue_filters=Favorite Issue Filters
my_account.favorite_measure_filters=Favorite Measure Filters
+my_account.notifications=Notifications
+my_account.no_project_notifications=You have not set project notifications yet.