<commit_before>import CreateFeatureToggle from '../../page/features/create';
import CopyFeatureToggle from '../../page/features/copy';
import ViewFeatureToggle from '../../page/features/show';
import Features from '../../page/features';
import CreateStrategies from '../../page/strategies/create';
import StrategyView from '../../page/strategies/show';
import Strategies from '../../page/strategies';
import HistoryPage from '../../page/history';
import HistoryTogglePage from '../../page/history/toggle';
import ShowArchive from '../../page/archive/show';
import Archive from '../../page/archive';
import Applications from '../../page/applications';
import ApplicationView from '../../page/applications/view';
import ContextFields from '../../page/context';
import CreateContextField from '../../page/context/create';
import EditContextField from '../../page/context/edit';
import CreateProject from '../../page/project/create';
import ListTagTypes from '../../page/tag-types';
import CreateTagType from '../../page/tag-types/create';
import EditTagType from '../../page/tag-types/edit';
import ListTags from '../../page/tags';
import CreateTag from '../../page/tags/create';
import Addons from '../../page/addons';
import AddonsCreate from '../../page/addons/create';
import AddonsEdit from '../../page/addons/edit';
import Admin from '../admin';
import AdminApi from '../admin/api';
import AdminUsers from '../admin/users';
import AdminInvoice from '../admin/invoice';
import AdminAuth from '../admin/auth';
import Login from '../user/Login/Login';
import { P, C, E, EEA } from '../common/flags';
import NewUser from '../user/NewUser';
import ResetPassword from '../user/ResetPassword/ResetPassword';
import ForgottenPassword from '../user/ForgottenPassword/ForgottenPassword';
import ProjectListNew from '../project/ProjectList/ProjectList';
import Project from '../project/Project/Project';
import RedirectFeatureViewPage from '../../page/features/redirect';
import RedirectArchive from '../feature/RedirectArchive/RedirectArchive';
import EnvironmentList from '../environments/EnvironmentList/EnvironmentList';
import CreateEnvironment from '../environments/CreateEnvironment/CreateEnvironment';
import FeatureView2 from '../feature/FeatureView2/FeatureView2';
import FeatureCreate from '../feature/FeatureCreate/FeatureCreate';
import ProjectRoles from '../admin/ProjectRolesv1/ProjectRoles';

export const routes = [
    // Project
    {
        path: '/projects/create',
        parent: '/projects',
        title: 'Create',
        component: CreateProject,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/archived',
        title: ':name',
        parent: '/archive',
        component: RedirectArchive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/features/:name/:activeTab/copy',
        parent: '/projects/:id/features/:name/:activeTab',
        title: 'Copy',
        component: CopyFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/features2/:name/:activeTab/copy',
        parent: '/projects/:id/features/:name/:activeTab',
        title: 'Copy',
        component: CopyFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/features2/:featureId',
        parent: '/projects',
        title: 'FeatureView2',
        component: FeatureView2,
        type: 'protected',
        layout: 'main',
        flags: E,
        menu: {},
    },
    {
        path: '/projects/:id/features/:name/:activeTab',
        parent: '/projects',
        title: ':name',
        component: ViewFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/create-toggle',
        parent: '/projects/:id/features',
        title: 'Create feature toggle',
        component: FeatureCreate,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/features/:name',
        parent: '/features',
        title: ':name',
        component: RedirectFeatureViewPage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/:activeTab',
        parent: '/projects',
        title: ':id',
        component: Project,
        flag: P,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id',
        parent: '/projects',
        title: ':id',
        component: Project,
        flag: P,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects',
        title: 'Projects',
        component: ProjectListNew,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true },
    },

    // Features
    {
        path: '/features/:activeTab/:name',
        parent: '/features',
        title: ':name',
        component: RedirectFeatureViewPage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/features',
        title: 'Feature Toggles',
        component: Features,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true },
    },

    // Applications
    {
        path: '/applications/:name',
        title: ':name',
        parent: '/applications',
        component: ApplicationView,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/applications',
        title: 'Applications',
        component: Applications,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // Context
    {
        path: '/context/create',
        parent: '/context',
        title: 'Create',
        component: CreateContextField,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/context/edit/:name',
        parent: '/context',
        title: ':name',
        component: EditContextField,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/context',
        title: 'Context Fields',
        component: ContextFields,
        type: 'protected',
        flag: C,
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // Strategies
    {
        path: '/strategies/create',
        title: 'Create',
        parent: '/strategies',
        component: CreateStrategies,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/strategies/:activeTab/:strategyName',
        title: ':strategyName',
        parent: '/strategies',
        component: StrategyView,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/strategies',
        title: 'Strategies',
        component: Strategies,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/environments/create',
        title: 'Environments',
        component: CreateEnvironment,
        parent: '/environments',
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/environments',
        title: 'Environments',
        component: EnvironmentList,
        type: 'protected',
        layout: 'main',
        flag: EEA,
        menu: { mobile: true, advanced: true },
    },

    // Tags
    {
        path: '/tag-types/create',
        parent: '/tag-types',
        title: 'Create',
        component: CreateTagType,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tag-types/edit/:name',
        parent: '/tag-types',
        title: ':name',
        component: EditTagType,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tag-types',
        title: 'Tag types',
        component: ListTagTypes,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/tags/create',
        parent: '/tags',
        title: 'Create',
        component: CreateTag,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tags',
        title: 'Tags',
        component: ListTags,
        hidden: true,
        type: 'protected',
        layout: 'main',
        menu: {},
    },

    // Addons
    {
        path: '/addons/create/:provider',
        parent: '/addons',
        title: 'Create',
        component: AddonsCreate,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/addons/edit/:id',
        parent: '/addons',
        title: 'Edit',
        component: AddonsEdit,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/addons',
        title: 'Addons',
        component: Addons,
        hidden: false,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // History
    {
        path: '/history/:toggleName',
        title: ':toggleName',
        parent: '/history',
        component: HistoryTogglePage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/history',
        title: 'Event History',
        component: HistoryPage,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },

    // Archive
    {
        path: '/projects/:id/archived/:name/:activeTab',
        title: ':name',
        parent: '/archive',
        component: ShowArchive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/archive',
        title: 'Archived Toggles',
        component: Archive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },

    // Admin
    {
        path: '/admin/api',
        parent: '/admin',
        title: 'API access',
        component: AdminApi,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/admin/users',
        parent: '/admin',
        title: 'Users',
        component: AdminUsers,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin/auth',
        parent: '/admin',
        title: 'Single Sign-On',
        component: AdminAuth,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin-invoices',
        title: 'Invoices',
        component: AdminInvoice,
        hidden: true,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin/roles',
        parent: '/admin',
        title: 'Project Roles',
        component: ProjectRoles,
        type: 'protected',
        layout: 'main',
        menu: {},
        hidden: true,
    },
    {
        path: '/admin',
        title: 'Admin',
        component: Admin,
        hidden: false,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/login',
        title: 'Log in',
        component: Login,
        type: 'unprotected',
        hidden: true,
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/new-user',
        title: 'New user',
        hidden: true,
        component: NewUser,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/reset-password',
        title: 'reset-password',
        hidden: true,
        component: ResetPassword,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/forgotten-password',
        title: 'reset-password',
        hidden: true,
        component: ForgottenPassword,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
];

export const getRoute = path => routes.find(route => route.path === path);

export const baseRoutes = routes.filter(route => !route.hidden);

const computeRoutes = () => {
    const mainNavRoutes = baseRoutes.filter(route => route.menu.advanced);
    const adminRoutes = routes.filter(route => route.menu.adminSettings);
    const mobileRoutes = routes.filter(route => route.menu.mobile);

    const computedRoutes = {
        mainNavRoutes,
        adminRoutes,
        mobileRoutes,
    };
    return () => {
        return computedRoutes;
    };
};

export const getRoutes = computeRoutes();
<commit_msg>fix: remove unused component in routes<commit_after>import CopyFeatureToggle from '../../page/features/copy';
import ViewFeatureToggle from '../../page/features/show';
import Features from '../../page/features';
import CreateStrategies from '../../page/strategies/create';
import StrategyView from '../../page/strategies/show';
import Strategies from '../../page/strategies';
import HistoryPage from '../../page/history';
import HistoryTogglePage from '../../page/history/toggle';
import ShowArchive from '../../page/archive/show';
import Archive from '../../page/archive';
import Applications from '../../page/applications';
import ApplicationView from '../../page/applications/view';
import ContextFields from '../../page/context';
import CreateContextField from '../../page/context/create';
import EditContextField from '../../page/context/edit';
import CreateProject from '../../page/project/create';
import ListTagTypes from '../../page/tag-types';
import CreateTagType from '../../page/tag-types/create';
import EditTagType from '../../page/tag-types/edit';
import ListTags from '../../page/tags';
import CreateTag from '../../page/tags/create';
import Addons from '../../page/addons';
import AddonsCreate from '../../page/addons/create';
import AddonsEdit from '../../page/addons/edit';
import Admin from '../admin';
import AdminApi from '../admin/api';
import AdminUsers from '../admin/users';
import AdminInvoice from '../admin/invoice';
import AdminAuth from '../admin/auth';
import Login from '../user/Login/Login';
import { P, C, E, EEA } from '../common/flags';
import NewUser from '../user/NewUser';
import ResetPassword from '../user/ResetPassword/ResetPassword';
import ForgottenPassword from '../user/ForgottenPassword/ForgottenPassword';
import ProjectListNew from '../project/ProjectList/ProjectList';
import Project from '../project/Project/Project';
import RedirectFeatureViewPage from '../../page/features/redirect';
import RedirectArchive from '../feature/RedirectArchive/RedirectArchive';
import EnvironmentList from '../environments/EnvironmentList/EnvironmentList';
import CreateEnvironment from '../environments/CreateEnvironment/CreateEnvironment';
import FeatureView2 from '../feature/FeatureView2/FeatureView2';
import FeatureCreate from '../feature/FeatureCreate/FeatureCreate';
import ProjectRoles from '../admin/ProjectRolesv1/ProjectRoles';

export const routes = [
    // Project
    {
        path: '/projects/create',
        parent: '/projects',
        title: 'Create',
        component: CreateProject,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/archived',
        title: ':name',
        parent: '/archive',
        component: RedirectArchive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/features/:name/:activeTab/copy',
        parent: '/projects/:id/features/:name/:activeTab',
        title: 'Copy',
        component: CopyFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/features2/:name/:activeTab/copy',
        parent: '/projects/:id/features/:name/:activeTab',
        title: 'Copy',
        component: CopyFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/features2/:featureId',
        parent: '/projects',
        title: 'FeatureView2',
        component: FeatureView2,
        type: 'protected',
        layout: 'main',
        flags: E,
        menu: {},
    },
    {
        path: '/projects/:id/features/:name/:activeTab',
        parent: '/projects',
        title: ':name',
        component: ViewFeatureToggle,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/create-toggle',
        parent: '/projects/:id/features',
        title: 'Create feature toggle',
        component: FeatureCreate,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:projectId/features/:name',
        parent: '/features',
        title: ':name',
        component: RedirectFeatureViewPage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id/:activeTab',
        parent: '/projects',
        title: ':id',
        component: Project,
        flag: P,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects/:id',
        parent: '/projects',
        title: ':id',
        component: Project,
        flag: P,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/projects',
        title: 'Projects',
        component: ProjectListNew,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true },
    },

    // Features
    {
        path: '/features/:activeTab/:name',
        parent: '/features',
        title: ':name',
        component: RedirectFeatureViewPage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/features',
        title: 'Feature Toggles',
        component: Features,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true },
    },

    // Applications
    {
        path: '/applications/:name',
        title: ':name',
        parent: '/applications',
        component: ApplicationView,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/applications',
        title: 'Applications',
        component: Applications,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // Context
    {
        path: '/context/create',
        parent: '/context',
        title: 'Create',
        component: CreateContextField,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/context/edit/:name',
        parent: '/context',
        title: ':name',
        component: EditContextField,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/context',
        title: 'Context Fields',
        component: ContextFields,
        type: 'protected',
        flag: C,
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // Strategies
    {
        path: '/strategies/create',
        title: 'Create',
        parent: '/strategies',
        component: CreateStrategies,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/strategies/:activeTab/:strategyName',
        title: ':strategyName',
        parent: '/strategies',
        component: StrategyView,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/strategies',
        title: 'Strategies',
        component: Strategies,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/environments/create',
        title: 'Environments',
        component: CreateEnvironment,
        parent: '/environments',
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/environments',
        title: 'Environments',
        component: EnvironmentList,
        type: 'protected',
        layout: 'main',
        flag: EEA,
        menu: { mobile: true, advanced: true },
    },

    // Tags
    {
        path: '/tag-types/create',
        parent: '/tag-types',
        title: 'Create',
        component: CreateTagType,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tag-types/edit/:name',
        parent: '/tag-types',
        title: ':name',
        component: EditTagType,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tag-types',
        title: 'Tag types',
        component: ListTagTypes,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/tags/create',
        parent: '/tags',
        title: 'Create',
        component: CreateTag,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/tags',
        title: 'Tags',
        component: ListTags,
        hidden: true,
        type: 'protected',
        layout: 'main',
        menu: {},
    },

    // Addons
    {
        path: '/addons/create/:provider',
        parent: '/addons',
        title: 'Create',
        component: AddonsCreate,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/addons/edit/:id',
        parent: '/addons',
        title: 'Edit',
        component: AddonsEdit,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/addons',
        title: 'Addons',
        component: Addons,
        hidden: false,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },

    // History
    {
        path: '/history/:toggleName',
        title: ':toggleName',
        parent: '/history',
        component: HistoryTogglePage,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/history',
        title: 'Event History',
        component: HistoryPage,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },

    // Archive
    {
        path: '/projects/:id/archived/:name/:activeTab',
        title: ':name',
        parent: '/archive',
        component: ShowArchive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/archive',
        title: 'Archived Toggles',
        component: Archive,
        type: 'protected',
        layout: 'main',
        menu: {},
    },

    // Admin
    {
        path: '/admin/api',
        parent: '/admin',
        title: 'API access',
        component: AdminApi,
        type: 'protected',
        layout: 'main',
        menu: { mobile: true, advanced: true },
    },
    {
        path: '/admin/users',
        parent: '/admin',
        title: 'Users',
        component: AdminUsers,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin/auth',
        parent: '/admin',
        title: 'Single Sign-On',
        component: AdminAuth,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin-invoices',
        title: 'Invoices',
        component: AdminInvoice,
        hidden: true,
        type: 'protected',
        layout: 'main',
        menu: { adminSettings: true },
    },
    {
        path: '/admin/roles',
        parent: '/admin',
        title: 'Project Roles',
        component: ProjectRoles,
        type: 'protected',
        layout: 'main',
        menu: {},
        hidden: true,
    },
    {
        path: '/admin',
        title: 'Admin',
        component: Admin,
        hidden: false,
        type: 'protected',
        layout: 'main',
        menu: {},
    },
    {
        path: '/login',
        title: 'Log in',
        component: Login,
        type: 'unprotected',
        hidden: true,
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/new-user',
        title: 'New user',
        hidden: true,
        component: NewUser,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/reset-password',
        title: 'reset-password',
        hidden: true,
        component: ResetPassword,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
    {
        path: '/forgotten-password',
        title: 'reset-password',
        hidden: true,
        component: ForgottenPassword,
        type: 'unprotected',
        layout: 'standalone',
        menu: {},
    },
];

export const getRoute = path => routes.find(route => route.path === path);

export const baseRoutes = routes.filter(route => !route.hidden);

const computeRoutes = () => {
    const mainNavRoutes = baseRoutes.filter(route => route.menu.advanced);
    const adminRoutes = routes.filter(route => route.menu.adminSettings);
    const mobileRoutes = routes.filter(route => route.menu.mobile);

    const computedRoutes = {
        mainNavRoutes,
        adminRoutes,
        mobileRoutes,
    };
    return () => {
        return computedRoutes;
    };
};

export const getRoutes = computeRoutes();
<|endoftext|>


<commit_before>/**
 * TCP networking.
 * Basically it almost fully copies PyBitmessage behavior to be more
 * compatible with the rest of network.
 */

import bitmessage from "bitmessage";
import TcpTransport from "bitmessage/lib/net/tcp";
import conf from "../config";
import * as storage from "../storage";
import {DEFAULT_STREAM, MY_SERVICES, MY_USER_AGENT, getLogger} from "./common";

const messages = bitmessage.messages;
const logDebug = getLogger("TCP", "debug");
const logInfo = getLogger("TCP", "info");
const logWarn = getLogger("TCP", "warn");

export function init() {
  return new Promise(function(resolve) {
    // TODO(Kagami): Hardcode stream to connect to by default. We may
    // need better stream support in future.
    runOutcomingLoop({stream: DEFAULT_STREAM, limit: getOutcomingLimit()});
    if (!conf.get("tcp-trusted-peer")) {
      listenIncoming({
        stream: DEFAULT_STREAM,
        host: conf.get("tcp-host"),
        port: conf.get("tcp-port"),
      });
    }
    resolve();
  });
}

// Dictionary of connected/half-open transports accessed by IP.
const connected = {};
// Number of outcoming connections.
let outcomingNum = 0;

// Return whether the given host is already connected/half-open.
function isConnected(host) {
  return Object.prototype.hasOwnProperty.call(connected, host);
}

// Return limit of outcoming connections.
function getOutcomingLimit() {
  return conf.get("tcp-trusted-peer") ? 1 : 8;
}

// Return a promise that contains random known node.
function getNode(stream) {
  let trustedPeer = conf.get("tcp-trusted-peer");
  if (trustedPeer) {
    return Promise.resolve({
      host: trustedPeer[0],
      port: trustedPeer[1],
    });
  } else {
    // TODO(Kagami): Attempted connections list.
    let exclude = Object.keys(connected);
    return storage.knownNodes.getRandom(null, stream, exclude);
  }
}

function createTransport() {
  return new TcpTransport({
    services: MY_SERVICES,
    userAgent: MY_USER_AGENT,
    port: conf.get("tcp-port"),
  });
}

function runOutcomingLoop(opts) {
  if (outcomingNum >= opts.limit) {
    return setTimeout(runOutcomingLoop, 100, opts);
  }

  getNode(opts.stream).then(function({host, port}) {
    // Check whether we are already connected to the returned node's
    // host once more time (`getNode` also filters connected nodes) to
    // protect ourself against race condition because of async SQL
    // query.
    if (!isConnected(host)) {
      logInfo("Connecting to %s:%s", host, port);
      let transport = createTransport();
      outcomingNum++;
      transport.on("close", function() {
        outcomingNum--;
      });
      setupTransport({transport, host, port});
      transport.connect(port, host);
    }
    setTimeout(runOutcomingLoop, 100, opts);
  }).catch(function(err) {
    logDebug(
      "Failed to find node to connect (%s), sleeping for 3 seconds",
      err.message);
    setTimeout(runOutcomingLoop, 3000, opts);
  });
}

function listenIncoming(opts) {
  let server = createTransport();
  // TODO(Kagami): Pass new connection info as an object?
  server.on("connection", function(transport, host, port) {
    logInfo("Got new connection from %s:%s", host, port);
    if (isConnected(host)) {
      logInfo("We are already connected to %s, closing connection", host);
      transport.close();
      return;
    }
    setupTransport({transport, host, port});
  });
  server.listen(opts.port, opts.host);
  logInfo("Listening at %s:%s", opts.host, opts.port);
}

// Report info about current connections.
function logconns() {
  let allNum = Object.keys(connected).length;
  logDebug("Total %s connection(s) (%s outcoming)", allNum, outcomingNum);
}

// Human-readably size of the message.
function getsize(payload) {
  // Message header length is 24 bytes.
  let len = payload.length + 24;
  if (len >= 1024) {
    return (len / 1024).toFixed(2) + "KiB";
  } else {
    return len + "B";
  }
}

// Setup event handlers for a new incoming/outcoming connection.
function setupTransport({transport, host, port}) {
  let start = new Date().getTime();
  connected[host] = transport;
  logconns();

  transport.on("established", function() {
    let delta = (new Date().getTime() - start) / 1000;
    logInfo("Connection to %s:%s was established in %ss", host, port, delta);

    transport.on("message", function(command, payload) {
      let start = new Date().getTime();
      logDebug(
        "Got new message '%s' (%s) from %s:%s",
        command, getsize(payload), host, port);
      let handler = messageHandlers[command];
      if (!handler) {
        return logWarn(
          "Skip unknown message '%s' from %s:%s",
          command, host, port);
      }

      // Process message.
      // FIXME(Kagami): Timing attack mitigation.
      try {
        handler({transport, host, port, command, payload});
      } catch(err) {
        return logWarn(
          "Failed to process message '%s' (%s) from %s:%s",
          command, err.message, host, port);
      }

      let delta = (new Date().getTime() - start) / 1000;
      logDebug(
        "Message '%s' from %s:%s was successfully processed in %ss",
        command, host, port, delta);
    });
  });

  transport.on("error", function(err) {
    logDebug("Connection error (%s) from %s:%s", err.message, host, port);
  });

  transport.on("close", function() {
    logInfo("Connection to %s:%s was closed", host, port);
    delete connected[host];
    logconns();
  });
}

// NOTE(Kagami): We need hoisting to use it in `setupTransport` function
// above.
var messageHandlers = {
  error: function({payload, host, port}) {
    // Just display incoming error message.
    let decoded = messages.error.decodePayload(payload);
    let text = `Got error message with type ${decoded.fatal} `;
    text += `from ${host}:${port}: ${decoded.errorText}`;
    if (decoded.banTime) {
      text += `; ban time is ${decoded.banTime}s`;
    }
    if (decoded.vector) {
      let hash = decoded.vector.toString("hex");
      text += `; this concerns inventory entry ${hash}`;
    }
    logWarn(text);
  },
  ping: function({transport}) {
    transport.send("pong");
  },
  addr: function({payload}) {
    let decoded = messages.addr.decodePayload(payload);
    logDebug("Got %s network address(es)", decoded.addrs.length);
  },
  inv: function() {
  },
  getdata: function() {
  },
  object: function() {
  },
};
<commit_msg>Cosmetics<commit_after>/**
 * TCP networking.
 * Basically it almost fully copies PyBitmessage behavior to be more
 * compatible with the rest of network.
 */

import bitmessage from "bitmessage";
import TcpTransport from "bitmessage/lib/net/tcp";
import conf from "../config";
import * as storage from "../storage";
import {DEFAULT_STREAM, MY_SERVICES, MY_USER_AGENT, getLogger} from "./common";

const messages = bitmessage.messages;
const logDebug = getLogger("TCP", "debug");
const logInfo = getLogger("TCP", "info");
const logWarn = getLogger("TCP", "warn");

export function init() {
  return new Promise(function(resolve) {
    // TODO(Kagami): Hardcode stream to connect to by default. We may
    // need better stream support in future.
    runOutcomingLoop({stream: DEFAULT_STREAM, limit: getOutcomingLimit()});
    if (!conf.get("tcp-trusted-peer")) {
      listenIncoming({
        stream: DEFAULT_STREAM,
        host: conf.get("tcp-host"),
        port: conf.get("tcp-port"),
      });
    }
    resolve();
  });
}

// Dictionary of connected/half-open transports accessed by IP.
const connected = {};
// Number of outcoming connections.
let outcomingNum = 0;

// Return whether the given host is already connected/half-open.
function isConnected(host) {
  return Object.prototype.hasOwnProperty.call(connected, host);
}

// Return limit of outcoming connections.
function getOutcomingLimit() {
  return conf.get("tcp-trusted-peer") ? 1 : 8;
}

// Return a promise that contains random known node.
function getNode(stream) {
  let trustedPeer = conf.get("tcp-trusted-peer");
  if (trustedPeer) {
    return Promise.resolve({
      host: trustedPeer[0],
      port: trustedPeer[1],
    });
  } else {
    // TODO(Kagami): Attempted connections list.
    let exclude = Object.keys(connected);
    return storage.knownNodes.getRandom(null, stream, exclude);
  }
}

function createTransport() {
  return new TcpTransport({
    services: MY_SERVICES,
    userAgent: MY_USER_AGENT,
    port: conf.get("tcp-port"),
  });
}

function runOutcomingLoop(opts) {
  if (outcomingNum >= opts.limit) {
    return setTimeout(runOutcomingLoop, 100, opts);
  }

  getNode(opts.stream).then(function({host, port}) {
    // Check whether we are already connected to the returned node's
    // host once more time (`getNode` also filters connected nodes) to
    // protect ourself against race condition because of async SQL
    // query.
    if (!isConnected(host)) {
      logInfo("Connecting to %s:%s", host, port);
      let transport = createTransport();
      outcomingNum++;
      transport.on("close", function() {
        outcomingNum--;
      });
      setupTransport({transport, host, port});
      transport.connect(port, host);
    }
    setTimeout(runOutcomingLoop, 100, opts);
  }).catch(function(err) {
    logDebug(
      "Failed to find node to connect (%s), sleeping for 3 seconds",
      err.message);
    setTimeout(runOutcomingLoop, 3000, opts);
  });
}

function listenIncoming(opts) {
  let server = createTransport();
  // TODO(Kagami): Pass new connection info as an object?
  server.on("connection", function(transport, host, port) {
    logInfo("Got new connection from %s:%s", host, port);
    if (isConnected(host)) {
      logInfo("We are already connected to %s, closing connection", host);
      transport.close();
      return;
    }
    setupTransport({transport, host, port});
  });
  server.listen(opts.port, opts.host);
  logInfo("Listening at %s:%s", opts.host, opts.port);
}

// Report info about current connections.
function logConnInfo() {
  let allNum = Object.keys(connected).length;
  logDebug("Total %s connection(s) (%s outcoming)", allNum, outcomingNum);
}

// Human-readably size of the message.
function getSize(payload) {
  // Message header length is 24 bytes.
  let len = payload.length + 24;
  if (len >= 1024) {
    return (len / 1024).toFixed(2) + "KiB";
  } else {
    return len + "B";
  }
}

// Setup event handlers for a new incoming/outcoming connection.
function setupTransport({transport, host, port}) {
  let start = new Date().getTime();
  connected[host] = transport;
  logConnInfo();

  transport.on("established", function() {
    let delta = (new Date().getTime() - start) / 1000;
    logInfo("Connection to %s:%s was established in %ss", host, port, delta);

    transport.on("message", function(command, payload) {
      let start = new Date().getTime();
      logDebug(
        "Got new message '%s' (%s) from %s:%s",
        command, getSize(payload), host, port);
      let handler = messageHandlers[command];
      if (!handler) {
        return logInfo(
          "Skip unknown message '%s' from %s:%s",
          command, host, port);
      }

      // Process message.
      // FIXME(Kagami): Timing attack mitigation.
      try {
        handler({transport, host, port, command, payload});
      } catch(err) {
        return logWarn(
          "Failed to process message '%s' (%s) from %s:%s",
          command, err.message, host, port);
      }

      let delta = (new Date().getTime() - start) / 1000;
      logDebug(
        "Message '%s' from %s:%s was successfully processed in %ss",
        command, host, port, delta);
    });
  });

  transport.on("error", function(err) {
    logDebug("Connection error (%s) from %s:%s", err.message, host, port);
  });

  transport.on("close", function() {
    logInfo("Connection to %s:%s was closed", host, port);
    delete connected[host];
    logConnInfo();
  });
}

// NOTE(Kagami): We need hoisting to use this variable in
// `setupTransport` function above.
var messageHandlers = {
  error: function({payload, host, port}) {
    // Just display incoming error message.
    let decoded = messages.error.decodePayload(payload);
    let type = messages.error.type2str(decoded.fatal);
    let text = `Got error message with type ${type} `;
    text += `from ${host}:${port}: ${decoded.errorText}`;
    if (decoded.banTime) {
      text += `; ban time is ${decoded.banTime}s`;
    }
    if (decoded.vector) {
      let hash = decoded.vector.toString("hex");
      text += `; this concerns inventory entry ${hash}`;
    }
    logWarn(text);
  },

  ping: function({transport}) {
    transport.send("pong");
  },

  addr: function({payload}) {
    let decoded = messages.addr.decodePayload(payload);
    logDebug("Got %s network address(es)", decoded.addrs.length);
  },

  inv: function() {
  },

  getdata: function() {
  },

  object: function() {
  },
};
<|endoftext|>


<commit_before>import React from 'react';
import { connect } from 'react-redux';
import { Tooltip } from 'react-leaflet';
import strftime from 'strftime';
import Button from 'react-bootstrap/lib/Button';
import PropTypes from 'prop-types';

import MarkerWithInnerLabel from 'fm3/components/leaflet/MarkerWithInnerLabel';
import { toastsAdd } from 'fm3/actions/toastsActions';

import 'fm3/styles/changesets.scss';

function Changesets({ changesets, onShowChangesetDetail }) {
  return (

      { changesets.map(changeset => (
        <MarkerWithInnerLabel
          faIcon="pencil"
          key={changeset.id}
          faIconLeftPadding="2px"
          position={L.latLng(changeset.centerLat, changeset.centerLon)}
          onClick={() => onShowChangesetDetail(changeset)}
        >
          <Tooltip className="compact" offset={new L.Point(9, -25)} direction="right" permanent>

              {changeset.userName}: {(changeset.description || '/bez popisu/').substring(0, 20)} {changeset.description && changeset.description.length >= 20 ? '...' : ''}

          </Tooltip>
        </MarkerWithInnerLabel>
      )) }

  );
}

Changesets.propTypes = {
  changesets: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string.isRequired,
    centerLat: PropTypes.number.isRequired,
    centerLon: PropTypes.number.isRequired,
    userName: PropTypes.string.isRequired,
    description: PropTypes.string,
    closedAt: PropTypes.instanceOf(Date).isRequired,
  })),
  onShowChangesetDetail: PropTypes.func.isRequired,
};

export default connect(
  state => ({
    changesets: state.changesets.changesets,
  }),
  dispatch => ({
    onShowChangesetDetail(changeset) {
      const message = (

            autor:{' '}
            <a
              href={`https://www.openstreetmap.org/user/${encodeURIComponent(changeset.userName)}`}
              target="_blank"
              rel="noopener noreferrer"
            >{changeset.userName}

popis: {changeset.description || '/bez popisu/'}

čas: {strftime('%d. %m. %H:%M', changeset.closedAt)}

            Viac detailov na{' '}
            <Button bsSize="small" onClick={() => window.open(`https://www.openstreetmap.org/changeset/${changeset.id}`)}>osm.org</Button>
            <Button bsSize="small" onClick={() => window.open(`https://overpass-api.de/achavi/?changeset=${changeset.id}`)}>achawi</Button>

      );

      dispatch(toastsAdd({
        collapseKey: 'changeset.detail',
        message,
        cancelType: ['SET_TOOL', 'CHANGESETS_REFRESH'],
        style: 'info',
      }));
    },
  }),
)(Changesets);
<commit_msg>#146: tuneup changeset detail<commit_after>import React from 'react';
import { connect } from 'react-redux';
import { Tooltip } from 'react-leaflet';
import strftime from 'strftime';
import PropTypes from 'prop-types';

import MarkerWithInnerLabel from 'fm3/components/leaflet/MarkerWithInnerLabel';
import { toastsAdd } from 'fm3/actions/toastsActions';

import 'fm3/styles/changesets.scss';

function Changesets({ changesets, onShowChangesetDetail }) {
  return (

      { changesets.map(changeset => (
        <MarkerWithInnerLabel
          faIcon="pencil"
          key={changeset.id}
          faIconLeftPadding="2px"
          position={L.latLng(changeset.centerLat, changeset.centerLon)}
          onClick={() => onShowChangesetDetail(changeset)}
        >
          <Tooltip className="compact" offset={new L.Point(9, -25)} direction="right" permanent>

              {changeset.userName}: {(changeset.description || '/bez popisu/').substring(0, 20)} {changeset.description && changeset.description.length >= 20 ? '...' : ''}

          </Tooltip>
        </MarkerWithInnerLabel>
      )) }

  );
}

Changesets.propTypes = {
  changesets: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string.isRequired,
    centerLat: PropTypes.number.isRequired,
    centerLon: PropTypes.number.isRequired,
    userName: PropTypes.string.isRequired,
    description: PropTypes.string,
    closedAt: PropTypes.instanceOf(Date).isRequired,
  })),
  onShowChangesetDetail: PropTypes.func.isRequired,
};

export default connect(
  state => ({
    changesets: state.changesets.changesets,
  }),
  dispatch => ({
    onShowChangesetDetail(changeset) {
      const message = (

            autor:{' '}
            <a
              href={`https://www.openstreetmap.org/user/${encodeURIComponent(changeset.userName)}`}
              target="_blank"
              rel="noopener noreferrer"
            >{changeset.userName}

popis: {changeset.description || '/bez popisu/'}

čas: {strftime('%d. %m. %H:%M', changeset.closedAt)}

            Viac detailov na{' '}
            <a
              href={`https://www.openstreetmap.org/changeset/${changeset.id}`}
              target="_blank"
              rel="noopener noreferrer"
            >osm.org,{' '}
            <a
              href={`https://overpass-api.de/achavi/?changeset=${changeset.id}`}
              target="_blank"
              rel="noopener noreferrer"
            >Achavi

      );

      dispatch(toastsAdd({
        collapseKey: 'changeset.detail',
        message,
        cancelType: ['SET_TOOL', 'CHANGESETS_REFRESH'],
        style: 'info',
      }));
    },
  }),
)(Changesets);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

module.exports = function (grunt) {
  grunt.config('requirejs', {
    dist: {
      // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
      options: {
        baseUrl: '<%= yeoman.app %>/scripts',
        // since nocache is a requirejs plugin and not stubbed, it must
        // be added manually to the bundle.
        deps: ['nocache'],
        findNestedDependencies: true,
        // TODO: (Issue #560) Figure out how to make sourcemaps work with grunt-usemin
        // https://github.com/yeoman/grunt-usemin/issues/30
        //generateSourceMaps: true,
        keepBuildDir: true,
        mainConfigFile: '<%= yeoman.app %>/scripts/require_config.js',
        name: 'main',
        optimize: 'none',
        out: '<%= yeoman.tmp %>/scripts/main.js',
        // required to support SourceMaps
        // http://requirejs.org/docs/errors.html#sourcemapcomments
        preserveLicenseComments: false,
        replaceRequireScript: [{
          files: ['<%= yeoman.page_template_dist %>/{,*/}index.html'],
          module: 'main',
          modulePath: '/scripts/main'
        }],
        stubModules: [
          'text',
          'stache'
        ],
        useStrict: true,
        wrap: true
      }
    }
  });
};
<commit_msg>fix(build): extend r.js timeout for building production<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

module.exports = function (grunt) {
  grunt.config('requirejs', {
    dist: {
      // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
      options: {
        baseUrl: '<%= yeoman.app %>/scripts',
        // since nocache is a requirejs plugin and not stubbed, it must
        // be added manually to the bundle.
        deps: ['nocache'],
        findNestedDependencies: true,
        keepBuildDir: true,
        mainConfigFile: '<%= yeoman.app %>/scripts/require_config.js',
        name: 'main',
        optimize: 'none',
        out: '<%= yeoman.tmp %>/scripts/main.js',
        // required to support SourceMaps
        // http://requirejs.org/docs/errors.html#sourcemapcomments
        preserveLicenseComments: false,
        replaceRequireScript: [{
          files: ['<%= yeoman.page_template_dist %>/{,*/}index.html'],
          module: 'main',
          modulePath: '/scripts/main'
        }],
        stubModules: [
          'text',
          'stache'
        ],
        useStrict: true,
        // See issue #3166, extending waitSeconds because r.js cannot
        // parse the dependency tree in time on slow machines
        waitSeconds: 20,
        wrap: true
      }
    }
  });
};
<|endoftext|>


<commit_before>var Config = require('./config');
var options = require('./config').options;
var Links = require('./helpers/links');
var Overlay = require('./helpers/overlay');
var Song = require('./helpers/manageSongs');

chrome.storage.local.get(["autorate", "rating", "downloadToggle", "downloadType", "downloadedSongs", "displayOverlay"], function(settings) {
  for (var option in settings) {
    options[option] = settings[option] ? settings[option] : options[option];
  }
  options.downloadValue = Config.songTypes[options.downloadType][0];
  options.actionsAllowed = ~Config.disabledURLs.indexOf(window.location.href) ? false : true;
});

chrome.storage.onChanged.addListener(function(changes) {
  if (changes.autorate) {
    if (changes.autorate.newValue) {
      options.autorate = true;
    } else {
      options.autorate = false;
    }
  }

  if (changes.rating) {
    options.rating = changes.rating.newValue;
  }

  if (changes.downloadToggle) {
    if (changes.downloadToggle.newValue) {
      options.downloadToggle = true;
    } else {
      options.downloadToggle = false;
    }
  }

  if (changes.downloadType) {
    options.downloadType = changes.downloadType.newValue;
    options.downloadValue = Config.songTypes[options.downloadType][0];
  }

  if (changes.displayOverlay) {
    options.displayOverlay = changes.displayOverlay.newValue;
  }

  Overlay.create(options);
});

$(function() {
  var $artist = $("#artist_details li:first div.artist_details");
  var $featured = $("#artist_details li:nth-child(3) div.artist_details");
  var $featuring = $("#artist_details li:nth-child(3) div.artist_label");
  var $search = $("input[type=text]");
  var url = window.location.href;
  var hasNotBeenDownloaded = Song.hasNotBeenDownloaded();
  var alreadyDownloaded = $("div h4").text() === "Thank you for your feedback on this track!  Enjoy the download!";
  var focused = false;
  var rated = false;

  if ($(document).width() > 1300) {
    Overlay.create(options);
  }

  if (!hasNotBeenDownloaded || alreadyDownloaded) {
    rated = true;
  }

  if (options.autorate) {
    Song.rate(options.rating);
    if (options.downloadToggle && options.actionsAllowed && hasNotBeenDownloaded) {
      Song.download(rated);
    }
  }

  Links.create($artist);
  if ($featuring.text() === "Featuring") {
    Links.create($featured);
  }

  $search.focus(function() {
    focused = true;
  });
  $search.blur(function() {
    focused = false;
  });

  $(".searchArtist").click(function(e) {
    e.preventDefault();
    Links.searchArtist($(this).text());
  });

  $("body").keydown(function(e) {
    if (!focused) {
      var keyIsNumber = Config.keyCodes[e.keyCode];
      if (keyIsNumber) {
        if (options.actionsAllowed && options.downloadToggle) {
          Song.rate(keyIsNumber);
        }
      }
      if (e.keyCode === 68) {
        if (options.actionsAllowed && hasNotBeenDownloaded) {
          Song.download(rated);
        }
      }
      if (e.keyCode === 80) {
        Song.playPause();
      }

      if (e.shiftKey === true) {
        if (e.keyCode === 38) {
          options.downloadValue = options.downloadValue === 0 ? 6 : options.downloadValue - 1;
          $("#dropdownDL").val(options.downloadValue).trigger("change");
        }
        if (e.keyCode === 40) {
          options.downloadValue = options.downloadValue === 6 ? 0 : options.downloadValue + 1;
          $("#dropdownDL").val(options.downloadValue).trigger("change");
        }
      }
    }
  });

  $(window).resize(Overlay.throttledResize);
});
<commit_msg>[fix] Added uglify<commit_after>var Config = require('./config');
var options = require('./config').options;
var Links = require('./helpers/links');
var Overlay = require('./helpers/overlay');
var Song = require('./helpers/manageSongs');

chrome.storage.local.get(["autorate", "rating", "downloadToggle", "downloadType", "downloadedSongs", "displayOverlay"], function(settings) {
  for (var option in settings) {
    options[option] = settings[option] ? settings[option] : options[option];
  }
  options.downloadValue = Config.songTypes[options.downloadType][0];
  options.actionsAllowed = ~Config.disabledURLs.indexOf(window.location.href) ? false : true;
});
var blah;

chrome.storage.onChanged.addListener(function(changes) {
  if (changes.autorate) {
    if (changes.autorate.newValue) {
      options.autorate = true;
    } else {
      options.autorate = false;
    }
  }

  if (changes.rating) {
    options.rating = changes.rating.newValue;
  }

  if (changes.downloadToggle) {
    if (changes.downloadToggle.newValue) {
      options.downloadToggle = true;
    } else {
      options.downloadToggle = false;
    }
  }

  if (changes.downloadType) {
    options.downloadType = changes.downloadType.newValue;
    options.downloadValue = Config.songTypes[options.downloadType][0];
  }

  if (changes.displayOverlay) {
    options.displayOverlay = changes.displayOverlay.newValue;
  }

  Overlay.create(options);
});

$(function() {
  var $artist = $("#artist_details li:first div.artist_details");
  var $featured = $("#artist_details li:nth-child(3) div.artist_details");
  var $featuring = $("#artist_details li:nth-child(3) div.artist_label");
  var $search = $("input[type=text]");
  var url = window.location.href;
  var hasNotBeenDownloaded = Song.hasNotBeenDownloaded();
  var alreadyDownloaded = $("div h4").text() === "Thank you for your feedback on this track!  Enjoy the download!";
  var focused = false;
  var rated = false;

  if ($(document).width() > 1300) {
    Overlay.create(options);
  }

  if (!hasNotBeenDownloaded || alreadyDownloaded) {
    rated = true;
  }

  if (options.autorate) {
    Song.rate(options.rating);
    if (options.downloadToggle && options.actionsAllowed && hasNotBeenDownloaded) {
      Song.download(rated);
    }
  }

  Links.create($artist);
  if ($featuring.text() === "Featuring") {
    Links.create($featured);
  }

  $search.focus(function() {
    focused = true;
  });
  $search.blur(function() {
    focused = false;
  });

  $(".searchArtist").click(function(e) {
    e.preventDefault();
    Links.searchArtist($(this).text());
  });

  $("body").keydown(function(e) {
    if (!focused) {
      var keyIsNumber = Config.keyCodes[e.keyCode];
      if (keyIsNumber) {
        if (options.actionsAllowed && options.downloadToggle) {
          Song.rate(keyIsNumber);
        }
      }
      if (e.keyCode === 68) {
        if (options.actionsAllowed && hasNotBeenDownloaded) {
          Song.download(rated);
        }
      }
      if (e.keyCode === 80) {
        Song.playPause();
      }

      if (e.shiftKey === true) {
        if (e.keyCode === 38) {
          options.downloadValue = options.downloadValue === 0 ? 6 : options.downloadValue - 1;
          $("#dropdownDL").val(options.downloadValue).trigger("change");
        }
        if (e.keyCode === 40) {
          options.downloadValue = options.downloadValue === 6 ? 0 : options.downloadValue + 1;
          $("#dropdownDL").val(options.downloadValue).trigger("change");
        }
      }
    }
  });

  $(window).resize(Overlay.throttledResize);
});
<|endoftext|>


<commit_before>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.onDocumentOpen = function(path, doc, oldPath, callback) {
    ensureDaemon(callback);
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) |% )$/);
};

handler.getCacheCompletionRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return / ?(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/,%]|==|!=)\s*)*/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            if (r.replaceText === "print(^^)" && pythonVersion === "python2" && !/\.[^ ]*$/.test(options.line.substr(pos.column)))
                r.replaceText = "print";
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var line = options.line;
    if (!options.matches.length) {
        // Normally we wouldn't complete here, maybe we can complete for the next char?
        // Let's do so unless it looks like the next char will be a newline
        if (line[pos.column - 1] && /(?![:)}\]\s"'])./.test(line[pos.column - 1]))
            return callback(null, { predicted: "" });
    }
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_completer] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_completer] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + options.line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_completer] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<commit_msg>Revert "Merge pull request +11739 from c9/fix-php-completion"<commit_after>/**
 * jsonalyzer Python code completion
 *
 * @copyright 2015, Ajax.org B.V.
 * @author Lennart Kats <lennart add c9.io>
 */
define(function(require, exports, module) {

var baseHandler = require("plugins/c9.ide.language/base_handler");
var workerUtil = require("plugins/c9.ide.language/worker_util");

var KEYWORD_REGEX = new RegExp(
    "^(and|as|assert|break|class|continue|def|del|elif|else|except|exec|"
    + "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|"
    + "raise|return|try|while|with|yield)$"
);
var DAEMON_PORT = 10880;
var ERROR_PORT_IN_USE = 98;
var ERROR_NO_SERVER = 7;

var handler = module.exports = Object.create(baseHandler);
var pythonVersion = "python2";
var pythonPath = "";
var jediServer;
var launchCommand;
var showedJediError;
var daemon;

handler.handlesLanguage = function(language) {
    return language === "python";
};

handler.init = function(callback) {
    var emitter = handler.getEmitter();
    emitter.on("set_python_config", function(e) {
        pythonVersion = e.pythonVersion;
        pythonPath = e.pythonPath;
        if (daemon) {
            daemon.kill();
            daemon = null;
        }
    });
    emitter.on("set_python_scripts", function(e) {
        jediServer = e.jediServer;
        launchCommand = e.launchCommand;
    });
    callback();
};

handler.onDocumentOpen = function(path, doc, oldPath, callback) {
    ensureDaemon(callback);
};

handler.getIdentifierRegex = function() {
    return /\w/;
};

handler.getCompletionRegex = function() {
    return (/(\.|\b(import|from|if|while|from|raise|return) |% )$/);
};

handler.getCacheCompletionRegex = function() {
     // Match strings that can be an expression or its prefix, i.e.
     // keywords/identifiers followed by whitespace and/or operators
    return /(\b\w+\s+|\b(if|while|for|print)\s*\(|([{[\-+*%<>!|&/,%]|==|!=)\s*)+/;
};

/**
 * Complete code at the current cursor position.
 */
handler.complete = function(doc, fullAst, pos, options, callback) {
    callDaemon("completions", handler.path, doc, pos, options, function(err, results, meta) {
        if (err) return callback(err);

        results && results.forEach(function beautifyCompletion(r) {
            r.isContextual = true;
            r.guessTooltip = true;
            r.replaceText = r.replaceText || r.name;
            r.priority = r.name[0] === "_" || r.replaceText === r.replaceText.toUpperCase() ? 3 : 4;
            r.icon = r.icon || "property";
            r.icon = r.name[0] === "_" ? r.icon.replace(/2?$/, "2") : r.icon;
            r.noDoc = options.noDoc;
            if (!r.doc)
                return;
            var docLines = r.doc.split(/\r\n|\n|\r/);
            var docBody = docLines.slice(2).join("\n");
            r.docHeadHtml = workerUtil.filterDocumentation(docLines[0]).replace(/^([A-Za-z0-9$_]+\()self, /, "$1");
            r.doc = workerUtil.filterDocumentation(docBody.replace(/``/g, "'"));
        });
        callback(null, results);
    });
};

/**
 * Jump to the definition of what's under the cursor.
 */
handler.jumpToDefinition = function(doc, fullAst, pos, options, callback) {
    callDaemon("goto_definitions", handler.path, doc, pos, options, callback);
};

/**
 * Predict how to complete code next. Did the user just type 'mat'?
 * Then we probably only have a completion 'math'. So we can predict
 * that the user may type 'math.' next and precompute completions.
 */
handler.predictNextCompletion = function(doc, fullAst, pos, options, callback) {
    var predicted = options.matches.filter(function(m) {
        return m.isContextual
            && m.icon !== "method"
            && !m.replaceText.match(KEYWORD_REGEX);
    });
    var line = doc.getLine(pos.row);
    if (predicted.length > 0 && "import".substr(0, line.length) === line)
        return callback(null, "import ");
    if (predicted.length !== 1)
        return callback();
    if (/^\s+import /.test(line))
        return callback();
    console.log("[python_completer] Predicted our next completion will be for " + predicted[0].replaceText + ".");
    callback(null, {
        predicted: predicted[0].replaceText + ".",
        showEarly: predicted[0].replaceText === "self" || predicted[0].icon === "package"
    });
};

/**
 * Invoke a function on our jedi python daemon. It runs as an HTTP daemon
 * so we use curl to send a request.
 */
function callDaemon(command, path, doc, pos, options, callback) {
    var line = doc.getLine(pos.row);
    ensureDaemon(function(err, dontRetry) {
        if (err) return callback(err);

        var start = Date.now();
        workerUtil.execAnalysis(
            "curl",
            {
                mode: "stdin",
                json: true,
                args: [
                    "-s", "--data-binary", "@-", // get input from stdin
                    "localhost:" + DAEMON_PORT + "?mode=" + command
                    + "&row=" + (pos.row + 1) + "&column=" + pos.column
                    + "&path=" + path.replace(/^\//, "")
                    + (options.noDoc ? "&nodoc=1" : ""),
                ],
            },
            function onResult(err, stdout, stderr, meta) {
                if (err) {
                    if (err.code === ERROR_NO_SERVER && !dontRetry) {
                        daemon = null;
                        return callDaemon(command, path, doc, pos, options, callback);
                    }
                    return callback(err);
                }

                if (typeof stdout !== "object")
                    return callback(new Error("Couldn't parse python-jedi output: " + stdout));

                console.log("[python_completer] " + command + " in " + (Date.now() - start)
                    + "ms (jedi: " + meta.serverTime + "ms): "
                    + line.substr(0, pos.column));

                callback(null, stdout, meta);
            }
        );
    });
}

/**
 * Make sure we're running a jedi daemon (../server/jedi_server.py).
 * It listens on a port in the workspace container or host.
 */
function ensureDaemon(callback) {
    if (daemon)
        return done(daemon.err);

    daemon = {
        err: new Error("Still starting daemon, enhance your calm"),
        kill: function() {
            this.killed = true;
        }
    };

    workerUtil.spawn(
        "bash",
        {
            args: [
                "-c", launchCommand, "--", pythonVersion,
                "$PYTHON -c '" + jediServer + "' daemon --port " + DAEMON_PORT
            ],
            env: { PYTHONPATH: pythonPath },
        },
        function(err, child) {
            var output = "";
            if (err) {
                daemon.err = err;
                return workerUtil.showError("Could not start python completion daemon. Please reload to try again.");
            }
            daemon = child;
            daemon.err = null;

            if (daemon.killed)
                daemon.kill();

            // We (re)start the daemon after 10 minutes to conserve memory
            var killTimer = setTimeout(daemon.kill.bind(daemon), 10 * 60 * 1000);

            child.stderr.on("data", function(data) {
                output += data;
                if (/Daemon listening/.test(data))
                    done();
            });
            child.on("exit", function(code) {
                if (code === ERROR_PORT_IN_USE) // someone else running daemon?
                    return done(null, true);
                if (!code || /Daemon listening/.test(output)) // everything ok, try again later
                    daemon = null;
                clearTimeout(killTimer);
                done(code && new Error("[python_completer] Daemon failed: " + output));
            });
        }
    );

    function done(err) {
        if (err && /No module named jedi/.test(err.message) && !showedJediError) {
            workerUtil.showError("Jedi not found. Please run 'pip install jedi' or 'sudo pip install jedi' to enable Python code completion.");
            showedJediError = true;
        }
        callback && callback(err);
        callback = null;
    }
}

});<|endoftext|>


<commit_before>'use strict';

import React from 'react/addons';
import {GoogleMaps, Marker} from 'react-google-maps';
var MapComponent = require('components/Map');
var Modal = require('components/Modal');
var CategoriesAction = require('actions/CategoriesActionCreators');
var GeoObjectsAction = require('actions/GeoObjectActionCreators');
var GeoListTable = require('components/GeoObjectsTable');
var GeoObjectEditor = require('components/GeoObjectEditor');
var _ = require('underscore');

require('styles/GeoDetails.less');

var GeoDetails = React.createClass({

    /**
     * Click handler for new category prompt
     * @param event
     */
    handlePromptNewCategory: function (event) {
        this.refs.addCategoryModalForm.show();
        event.preventDefault();
    },

    /**
     * Add new category form cancel button handler
     * @param event
     */
    onCancelNewCategory: function (event) {
        this.refs.addCategoryModalForm.hide();
        event.preventDefault();
    },

    /**
     * Create new category with raw data
     * @param event
     */
    onAddNewCategoryPrompt: function (event) {
        CategoriesAction.addOneCategory({
            name: this.refs.newCategoryName.getDOMNode().value
        });
        event.preventDefault();
    },

    /**
     * Click handler for new geo object
     * @param event
     */
    showGeoObjectFormObject: function (event) {
        this.setState({geoEditorIsVisible:true});
        event.preventDefault();
    },

    /**
     * Handle user edit object prompt
     * @param event
     * @private
     */
    _editObjectHandler: function (event) {
        this.setState({
            geoObject:_.findWhere(this.props.geoObjects,{id:+event.target.getAttribute('data')}),
            geoEditorIsVisible:true
        });
    },

    /**
     * Cancel edit object handler
     * @private
     */
    _cancelObjectEditHandler: function () {
        this.setState({geoObject:{}, geoEditorIsVisible:false});
    },
    /**
     * Add one object handler
     * @private
     */
    _addNewObjectHandler: function () {
        this.setState({geoObject:{}, geoEditorIsVisible:false});
    },
    /**
     * Get map marker from given lat & lng coordinates
     * @param lat
     * @param lng
     * @private
     * @returns {object/undefined}
     */
    _getMarkerFromLatLng: function (lat, lng) {
        var marker;
        if (!isNaN(parseInt(lat)) && !isNaN(parseInt(lng))) {
            marker = {
                position: new google.maps.LatLng(lat, lng)
            };
        }
        return marker;
    },
    /**
     * Get marker with marker raw data
     * @param {object} marker The marker raw data
     * @returns {XML}
     * @private
     */
    _getMarkerComponent: function (marker) {
        var pinColor = Math.floor(Math.random()*16777215).toString(16);
        var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
            new google.maps.Size(21, 34),
            new google.maps.Point(0,0),
            new google.maps.Point(10, 34));
        //var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
        //    new google.maps.Size(40, 37),
        //    new google.maps.Point(0, 0),
        //    new google.maps.Point(12, 35));
        return (
            <Marker position={marker.position}
                    key={marker.key}
                    icon={pinImage}
                />
        );
    },

    getInitialState: function() {
        return {
            geoObject: {},
            geoEditorIsVisible: false,
            mapZoomLevel: 2,
            mapCenter: new google.maps.LatLng(0, 0),
            selectedLayer: ''

        };
    },
    getGeoObjectEditor: function () {
        if(this.state.geoEditorIsVisible){
            return(<GeoObjectEditor
                ref="geoObjectEditor"
                isVisible={this.state.geoEditorIsVisible}
                categories={this.props.categories}
                geoObject={this.state.geoObject}
                cancelObjectEditHandler={this._cancelObjectEditHandler}
                addNewObjectHandler={this._addNewObjectHandler}/>
            );
        }
    },
    componentWillReceiveProps: function(nextProps) {
        var geoObject = nextProps.geoObject;
        var mapZoomLevel = this.state.mapZoomLevel;
        var mapCenter = this.state.mapCenter;
        if(geoObject.name) {
            mapCenter = new google.maps.LatLng(geoObject.latitude, geoObject.longitude);
            mapZoomLevel = nextProps.zoomLevel;
        }
        this.setState({geoObject, mapCenter, mapZoomLevel});
    },
    componentDidMount: function () {

    },

    /**
     * Show object on map click handler
     * @param event
     */
    showObjectOnMapClickHandler: function (event) {
        this.refs.tabMap.getDOMNode().checked = true;
        var geoObject = _.findWhere(this.props.geoObjects,{id:+event.target.getAttribute('data')});
        this.setState({
            geoObject: geoObject,
            mapZoomLevel: 6,
            mapCenter: new google.maps.LatLng(geoObject.latitude, geoObject.longitude)
        });
    },

    /**
     * Layer selected handler
     * @param event
     * @private
     */
    _onCategoryLayerSelected: function (event) {
        this.setState({selectedLayer:event.target.value});
    },
    _getMarkers: function () {
        var markers = [];
        var marker;
        var selectedLayer = this.state.selectedLayer || _.first(this.props.categories);
        _.each(_.where(this.props.geoObjects,{category:selectedLayer}), function (geoObject, index) {
            marker = this._getMarkerFromLatLng(geoObject.latitude, geoObject.longitude);
            if (marker) {
                marker.key = index;
                markers.push(this._getMarkerComponent(marker));
            }
        }, this);
        return markers;
    },

    render: function () {
        return (

                        <input ref="tabMap" type="radio" id="tab-map" name="tab-group-2" defaultChecked/>
                        Карта

                            <GoogleMaps containerProps={{style: {height: "100%",width: "100%"}}}
                                        ref="map"
                                        googleMapsApi={google.maps}
                                        zoom={this.state.mapZoomLevel}
                                        center={this.state.mapCenter}
                                        >
                                {this._getMarkers()}
                            </GoogleMaps>

                        <input type="radio" id="tab-list" name="tab-group-2"/>
                        Список

                                Новая категория
                                Новый объект

                            <GeoListTable showObjectOnMapClickHandler={this.showObjectOnMapClickHandler} geoObjects={this.props.geoObjects} editObjectHandler={this._editObjectHandler}/>
                            <form>
                                <select onChange={this._onCategoryLayerSelected}>
                                    {this.props.categories.map(function (category) {
                                        return (<option key={category}>{category}</option>);
                                    })}
                                </select>
                            </form>

                <Modal visible={false} closable={true} ref="addCategoryModalForm">

Новая категория

                        <form className="modalForm">

                                Имя
                                <input type="text" name="name" size="25" ref="newCategoryName"/>

                                    <input type="button" value="Создать категорию" onClick={this.onAddNewCategoryPrompt}/>
                                    <input type="button" value="Отмена" onClick={this.onCancelNewCategory}/>

                        </form>

                </Modal>
                {this.getGeoObjectEditor()}

        );
    }
});

module.exports = GeoDetails;

<commit_msg>clear selected object<commit_after>'use strict';

import React from 'react/addons';
import {GoogleMaps, Marker} from 'react-google-maps';
var MapComponent = require('components/Map');
var Modal = require('components/Modal');
var CategoriesAction = require('actions/CategoriesActionCreators');
var GeoObjectsAction = require('actions/GeoObjectActionCreators');
var GeoListTable = require('components/GeoObjectsTable');
var GeoObjectEditor = require('components/GeoObjectEditor');
var _ = require('underscore');

require('styles/GeoDetails.less');

var GeoDetails = React.createClass({

    /**
     * Click handler for new category prompt
     * @param event
     */
    handlePromptNewCategory: function (event) {
        this.refs.addCategoryModalForm.show();
        event.preventDefault();
    },

    /**
     * Add new category form cancel button handler
     * @param event
     */
    onCancelNewCategory: function (event) {
        this.refs.addCategoryModalForm.hide();
        event.preventDefault();
    },

    /**
     * Create new category with raw data
     * @param event
     */
    onAddNewCategoryPrompt: function (event) {
        CategoriesAction.addOneCategory({
            name: this.refs.newCategoryName.getDOMNode().value
        });
        event.preventDefault();
    },

    /**
     * Click handler for new geo object
     * @param event
     */
    showGeoObjectFormObject: function (event) {
        this.setState({geoEditorIsVisible:true});
        event.preventDefault();
    },

    /**
     * Handle user edit object prompt
     * @param event
     * @private
     */
    _editObjectHandler: function (event) {
        this.setState({
            geoObject:_.findWhere(this.props.geoObjects,{id:+event.target.getAttribute('data')}),
            geoEditorIsVisible:true
        });
    },

    /**
     * Cancel edit object handler
     * @private
     */
    _cancelObjectEditHandler: function () {
        this.setState({geoObject:{}, geoEditorIsVisible:false});
    },
    /**
     * Add one object handler
     * @private
     */
    _addNewObjectHandler: function () {
        this.setState({geoObject:{}, geoEditorIsVisible:false});
    },
    /**
     * Get map marker from given lat & lng coordinates
     * @param lat
     * @param lng
     * @private
     * @returns {object/undefined}
     */
    _getMarkerFromLatLng: function (lat, lng) {
        var marker;
        if (!isNaN(parseInt(lat)) && !isNaN(parseInt(lng))) {
            marker = {
                position: new google.maps.LatLng(lat, lng)
            };
        }
        return marker;
    },
    /**
     * Get marker with marker raw data
     * @param {object} marker The marker raw data
     * @returns {XML}
     * @private
     */
    _getMarkerComponent: function (marker) {
        var pinColor = Math.floor(Math.random()*16777215).toString(16);
        var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
            new google.maps.Size(21, 34),
            new google.maps.Point(0,0),
            new google.maps.Point(10, 34));
        //var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
        //    new google.maps.Size(40, 37),
        //    new google.maps.Point(0, 0),
        //    new google.maps.Point(12, 35));
        return (
            <Marker position={marker.position}
                    key={marker.key}
                    icon={pinImage}
                />
        );
    },

    getInitialState: function() {
        return {
            geoObject: {},
            geoEditorIsVisible: false,
            mapZoomLevel: 2,
            mapCenter: new google.maps.LatLng(0, 0),
            selectedLayer: ''

        };
    },
    getGeoObjectEditor: function () {
        if(this.state.geoEditorIsVisible){
            return(<GeoObjectEditor
                ref="geoObjectEditor"
                isVisible={this.state.geoEditorIsVisible}
                categories={this.props.categories}
                geoObject={this.state.geoObject}
                cancelObjectEditHandler={this._cancelObjectEditHandler}
                addNewObjectHandler={this._addNewObjectHandler}/>
            );
        }
    },
    componentWillReceiveProps: function(nextProps) {
        var geoObject = nextProps.geoObject;
        var mapZoomLevel = this.state.mapZoomLevel;
        var mapCenter = this.state.mapCenter;
        if(geoObject.name) {
            mapCenter = new google.maps.LatLng(geoObject.latitude, geoObject.longitude);
            mapZoomLevel = nextProps.zoomLevel;
        }
        this.setState({geoObject, mapCenter, mapZoomLevel});
    },
    componentDidMount: function () {

    },

    /**
     * Show object on map click handler
     * @param event
     */
    showObjectOnMapClickHandler: function (event) {
        this.refs.tabMap.getDOMNode().checked = true;
        var geoObject = _.findWhere(this.props.geoObjects,{id:+event.target.getAttribute('data')});
        this.setState({
            geoObject: geoObject,
            mapZoomLevel: 6,
            mapCenter: new google.maps.LatLng(geoObject.latitude, geoObject.longitude)
        });
    },

    /**
     * Layer selected handler
     * @param event
     * @private
     */
    _onCategoryLayerSelected: function (event) {
        this.setState({selectedLayer:event.target.value});
    },
    _getMarkers: function () {
        var markers = [];
        var marker;
        var selectedLayer = this.state.selectedLayer || _.first(this.props.categories);
        _.each(_.where(this.props.geoObjects,{category:selectedLayer}), function (geoObject, index) {
            marker = this._getMarkerFromLatLng(geoObject.latitude, geoObject.longitude);
            if (marker) {
                marker.key = index;
                markers.push(this._getMarkerComponent(marker));
            }
        }, this);
        return markers;
    },

    /**
     * Clear selected geo object on tab changed
     * @private
     */
    _clearSelectedObject: function () {
        this.setState({geoObject:{}});
    },

    render: function () {
        return (

                        <input ref="tabMap" type="radio" id="tab-map" name="tab-group-2" defaultChecked/>
                        Карта

                            <GoogleMaps containerProps={{style: {height: "100%",width: "100%"}}}
                                        ref="map"
                                        googleMapsApi={google.maps}
                                        zoom={this.state.mapZoomLevel}
                                        center={this.state.mapCenter}
                                        >
                                {this._getMarkers()}
                            </GoogleMaps>

                        <input type="radio" id="tab-list" name="tab-group-2" onChange={this._clearSelectedObject}/>
                        Список

                                Новая категория
                                Новый объект

                            <GeoListTable showObjectOnMapClickHandler={this.showObjectOnMapClickHandler} geoObjects={this.props.geoObjects} editObjectHandler={this._editObjectHandler}/>
                            <form>
                                <select onChange={this._onCategoryLayerSelected}>
                                    {this.props.categories.map(function (category) {
                                        return (<option key={category}>{category}</option>);
                                    })}
                                </select>
                            </form>

                <Modal visible={false} closable={true} ref="addCategoryModalForm">

Новая категория

                        <form className="modalForm">

                                Имя
                                <input type="text" name="name" size="25" ref="newCategoryName"/>

                                    <input type="button" value="Создать категорию" onClick={this.onAddNewCategoryPrompt}/>
                                    <input type="button" value="Отмена" onClick={this.onCancelNewCategory}/>

                        </form>

                </Modal>
                {this.getGeoObjectEditor()}

        );
    }
});

module.exports = GeoDetails;

<|endoftext|>


<commit_before>const React = require('react');
const _merge = require('lodash/merge');

const StyleConstants = require('../constants/Style');
const Icon = require('../components/Icon');

const MessageBox = React.createClass({
  propTypes: {
    children: React.PropTypes.node,
    color: React.PropTypes.string,
    icon: React.PropTypes.string,
    styles: React.PropTypes.object,
    title: React.PropTypes.string
  },

  getInitialState () {
    return {
      isOpen: true
    };
  },

  _toggleMessageBox () {
    this.setState({
      isOpen: !this.state.isOpen
    });
  },

  render () {
    const styles = this.styles();

    return (

 {}} style={styles.header}>

            <Icon
              size={20}
              style={Object.assign({}, styles.icon, { marginRight: StyleConstants.Spacing.SMALL })}
              type={this.props.icon}
            />

{this.props.title}

          {this.props.children &&
            <Icon
              size={19}
              style={styles.icon}
              type={this.state.isOpen ? 'caret-up' : 'caret-down'}
            />
          }

        {this.state.isOpen &&

            {this.props.children}

        }

    );
  },

  styles () {
    return _merge({}, {
      component: {
        color: StyleConstants.Colors.WHITE,
        boxSizing: 'border-box'
      },
      header: {
        background: this.props.color,
        display: 'flex',
        cursor: this.props.children ? 'pointer' : 'auto',
        padding: StyleConstants.Spacing.XSMALL,
        alignItems: 'center'
      },
      leftHeader: {
        flex: 1,
        display: 'flex',
        alignItems: 'center'
      },
      title: {
        fontFamily: StyleConstants.Fonts.SEMIBOLD
      },
      icon: {
        fill: StyleConstants.Colors.WHITE
      },
      children: {
        backgroundColor: StyleConstants.adjustHexOpacity(this.props.color, 0.1),
        padding: this.props.children ? StyleConstants.Spacing.SMALL : null
      }
    }, this.props.styles);
  }
});

module.exports = MessageBox;
<commit_msg>killed unnecessary line break<commit_after>const React = require('react');
const _merge = require('lodash/merge');

const StyleConstants = require('../constants/Style');
const Icon = require('../components/Icon');

const MessageBox = React.createClass({
  propTypes: {
    children: React.PropTypes.node,
    color: React.PropTypes.string,
    icon: React.PropTypes.string,
    styles: React.PropTypes.object,
    title: React.PropTypes.string
  },

  getInitialState () {
    return {
      isOpen: true
    };
  },

  _toggleMessageBox () {
    this.setState({
      isOpen: !this.state.isOpen
    });
  },

  render () {
    const styles = this.styles();

    return (

 {}} style={styles.header}>

            <Icon
              size={20}
              style={Object.assign({}, styles.icon, { marginRight: StyleConstants.Spacing.SMALL })}
              type={this.props.icon}
            />

{this.props.title}

          {this.props.children &&
            <Icon
              size={19}
              style={styles.icon}
              type={this.state.isOpen ? 'caret-up' : 'caret-down'}
            />
          }

        {this.state.isOpen &&

            {this.props.children}

        }

    );
  },

  styles () {
    return _merge({}, {
      component: {
        color: StyleConstants.Colors.WHITE,
        boxSizing: 'border-box'
      },
      header: {
        background: this.props.color,
        display: 'flex',
        cursor: this.props.children ? 'pointer' : 'auto',
        padding: StyleConstants.Spacing.XSMALL,
        alignItems: 'center'
      },
      leftHeader: {
        flex: 1,
        display: 'flex',
        alignItems: 'center'
      },
      title: {
        fontFamily: StyleConstants.Fonts.SEMIBOLD
      },
      icon: {
        fill: StyleConstants.Colors.WHITE
      },
      children: {
        backgroundColor: StyleConstants.adjustHexOpacity(this.props.color, 0.1),
        padding: this.props.children ? StyleConstants.Spacing.SMALL : null
      }
    }, this.props.styles);
  }
});

module.exports = MessageBox;
<|endoftext|>