/* * Copyright 2014 Mirantis, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. **/ import $ from 'jquery'; import _ from 'underscore'; import i18n from 'i18n'; import Backbone from 'backbone'; import React from 'react'; import utils from 'utils'; import models from 'models'; import {backboneMixin, pollingMixin, dispatcherMixin} from 'component_mixins'; import {Popover, Link} from 'views/controls'; import {ChangePasswordDialog, ShowNodeInfoDialog} from 'views/dialogs'; export var Navbar = React.createClass({ mixins: [ dispatcherMixin('updateNodeStats', 'updateNodeStats'), dispatcherMixin('updateNotifications', 'updateNotifications'), backboneMixin('user'), backboneMixin('version'), backboneMixin('statistics'), backboneMixin('notifications', 'update change:status'), pollingMixin(20) ], togglePopover(popoverName) { return _.memoize((visible) => { this.setState((previousState) => { var nextState = {}; var key = popoverName + 'PopoverVisible'; nextState[key] = _.isBoolean(visible) ? visible : !previousState[key]; return nextState; }); }); }, setActive(url) { this.setState({activeElement: url}); }, shouldDataBeFetched() { return this.props.user.get('authenticated'); }, fetchData() { return Promise.all([ this.props.statistics.fetch(), this.props.notifications.fetch({limit: this.props.notificationsDisplayCount}) ]); }, updateNodeStats() { return this.props.statistics.fetch(); }, updateNotifications() { return this.props.notifications.fetch({limit: this.props.notificationsDisplayCount}); }, componentDidMount() { this.props.user.on('change:authenticated', (model, value) => { if (value) { this.startPolling(); } else { this.stopPolling(); this.props.statistics.clear(); this.props.notifications.reset(); } }); }, getDefaultProps() { return { notificationsDisplayCount: 5, elements: [ {label: 'environments', url: '/clusters'}, {label: 'equipment', url: '/equipment'}, {label: 'releases', url: '/releases'}, {label: 'plugins', url: '/plugins'}, {label: 'support', url: '/support'} ] }; }, getInitialState() { return {}; }, scrollToTop() { $('html, body').animate({scrollTop: 0}, 'fast'); }, render() { var unreadNotificationsCount = this.props.notifications.filter({status: 'unread'}).length; var authenticationEnabled = this.props.version.get('auth_required') && this.props.user.get('authenticated'); return (
); } }); var LanguagePopover = React.createClass({ changeLocale(locale, e) { e.preventDefault(); this.props.toggle(false); _.defer(() => { i18n.setLocale(locale); location.reload(); }); }, render() { var currentLocale = i18n.getCurrentLocale(); return ( ); } }); var StatisticsPopover = React.createClass({ mixins: [backboneMixin('statistics')], render() { var {toggle, statistics} = this.props; return (
  • {statistics.get('unallocated')} {i18n('navbar.stats.unallocated', {count: statistics.get('unallocated')})}
  • {statistics.get('total')} {i18n('navbar.stats.total', {count: statistics.get('total')})}
  • ); } }); var UserPopover = React.createClass({ mixins: [backboneMixin('user')], showChangePasswordDialog() { this.props.toggle(false); ChangePasswordDialog.show(); }, logout() { this.props.toggle(false); app.logout(); }, render() { var {toggle, user} = this.props; return (
    {i18n('common.username')}:

    {user.get('username')}

    ); } }); var NotificationsPopover = React.createClass({ mixins: [backboneMixin('notifications')], showNodeInfo(id) { this.props.toggle(false); var node = new models.Node({id}); node.fetch(); ShowNodeInfoDialog.show({node}); }, markAsRead() { var notificationsToMark = new models.Notifications( this.props.notifications.filter({status: 'unread'}) ); if (notificationsToMark.length) { this.setState({unreadNotificationsIds: notificationsToMark.map('id')}); notificationsToMark.toJSON = function() { return notificationsToMark.map((notification) => { notification.set({status: 'read'}); return _.pick(notification.attributes, 'id', 'status'); }); }; Backbone.sync('update', notificationsToMark); } }, componentDidMount() { this.markAsRead(); }, getInitialState() { return {unreadNotificationsIds: []}; }, renderNotification(notification) { var nodeId = notification.get('node_id'); var notificationClasses = { notification: true, clickable: nodeId, unread: notification.get('status') === 'unread' || _.includes(this.state.unreadNotificationsIds, notification.id) }; var iconClass = { error: 'glyphicon-exclamation-sign text-danger', warning: 'glyphicon-warning-sign text-warning', discover: 'glyphicon-bell' }[notification.get('topic')] || 'glyphicon-info-sign'; // show not more than 200 symbols of notification text var MAX_NOTIFICATION_LENGTH = 200; var message = _.truncate(notification.get('message'), { length: MAX_NOTIFICATION_LENGTH, separator: ' ' }); return (

    ); }, render() { var showMore = Backbone.history.getHash() !== 'notifications'; var {notifications, displayCount, toggle} = this.props; return ( {_.map(notifications.take(displayCount), this.renderNotification)} {showMore &&
    {i18n('notifications_popover.view_all_button')}
    }
    ); } }); export var Footer = React.createClass({ mixins: [backboneMixin('version')], render() { var version = this.props.version; return (
    {i18n('common.version')}: {version.get('release')}
    ); } }); export var PageLoadProgressBar = React.createClass({ mixins: [ dispatcherMixin('pageLoadStarted', 'showProgressBar'), dispatcherMixin('pageLoadFinished', 'hideProgressBar') ], getDefaultProps() { return { initialProgress: 10, maxProgress: 94, progressStep: 2, stepDelay: 300 }; }, getInitialState() { return { visible: false, progress: this.props.initialProgress }; }, showProgressBar() { this.setState({progress: this.props.initialProgress, visible: true}); this.activeInterval = setInterval(() => { if (this.state.progress < this.props.maxProgress) { this.setState({progress: this.state.progress + this.props.progressStep}); } }, this.props.stepDelay); }, hideProgressBar() { clearInterval(this.activeInterval); this.setState({progress: 100, visible: false}, () => { setTimeout(() => this.setState({progress: this.props.initialProgress}), 400); }); }, componentWillUnmount() { clearInterval(this.activeInterval); }, render() { return (
    ); } }); export var Breadcrumbs = React.createClass({ mixins: [ dispatcherMixin('updatePageLayout', 'refresh') ], getInitialState() { return {path: this.getBreadcrumbsPath()}; }, getBreadcrumbsPath() { var page = this.props.Page; return _.isFunction(page.breadcrumbsPath) ? page.breadcrumbsPath(this.props.pageOptions) : page.breadcrumbsPath; }, refresh() { this.setState({path: this.getBreadcrumbsPath()}); }, render() { return (
      {_.map(this.state.path, (breadcrumb, index) => { if (!_.isArray(breadcrumb)) breadcrumb = [breadcrumb, null, {active: true}]; var text = breadcrumb[0]; var link = breadcrumb[1]; var options = breadcrumb[2] || {}; if (!options.skipTranslation) { text = i18n('breadcrumbs.' + text, {defaultValue: text}); } if (options.active) { return
    1. {text}
    2. ; } else { return
    3. {text}
    4. ; } })}
    ); } }); export var DefaultPasswordWarning = React.createClass({ render() { return (
    {i18n('common.default_password_warning')}
    ); } }); export var BootstrapError = React.createClass({ render() { return (
    {this.props.text}
    ); } });