<commit_before>import { i18nMark } from "@lingui/react";
import { Trans } from "@lingui/macro";
import { routerShape, Link } from "react-router";
import React, { Suspense, lazy } from "react";
import createReactClass from "create-react-class";
import { StoreMixin } from "mesosphere-shared-reactjs";
import { Icon } from "@dcos/ui-kit";
import { ProductIcons } from "@dcos/ui-kit/dist/packages/icons/dist/product-icons-enum";
import { iconSizeS } from "@dcos/ui-kit/dist/packages/design-tokens/build/js/designTokens";

import DCOSStore from "#SRC/js/stores/DCOSStore";
import ResourcesUtil from "#SRC/js/utils/ResourcesUtil";

import Breadcrumb from "../components/Breadcrumb";
import Loader from "../components/Loader";
import BreadcrumbTextContent from "../components/BreadcrumbTextContent";
import ComponentList from "../components/ComponentList";
import Config from "../config/Config";
import HealthSorting from "../../../plugins/services/src/js/constants/HealthSorting";
import InternalStorageMixin from "../mixins/InternalStorageMixin";
import MesosSummaryStore from "../stores/MesosSummaryStore";
import Page from "../components/Page";
import Panel from "../components/Panel";
import ServiceList from "../../../plugins/services/src/js/components/ServiceList";
import StringUtil from "../utils/StringUtil";
import SidebarActions from "../events/SidebarActions";
import UnitHealthStore from "../stores/UnitHealthStore";
import DashboardHeadings from "../constants/DashboardHeadings";
import HealthUnitsList from "../structs/HealthUnitsList";

function getMesosState() {
  const states = MesosSummaryStore.get("states");
  const last = states.lastSuccessful();

  return {
    activeNodes: states.getActiveNodesByState(),
    hostCount: last.getActiveSlaves().length,
    usedResourcesStates: states.getResourceStatesForNodeIDs(),
    usedResources: last.getSlaveUsedResources(),
    tasks: last.getServiceList().sumTaskStates(),
    totalResources: last.getSlaveTotalResources()
  };
}

const ResourceTimeSeriesChart = lazy(() =>
  import(/* webpackChunkName: "resourcetimeserieschart" */ "../components/charts/ResourceTimeSeriesChart")
);
const HostTimeSeriesChart = lazy(() =>
  import(/* webpackChunkName: "hosttimeserieschart" */ "../components/charts/HostTimeSeriesChart")
);
const TasksChart = lazy(() =>
  import(/* webpackChunkName: "taskschart" */ "../components/charts/TasksChart")
);

const DashboardBreadcrumbs = () => {
  const crumbs = [
    <Breadcrumb key={0} title="Dashboard">
      <BreadcrumbTextContent>
        <Link to="/dashboard">
          <Trans render="span">Dashboard</Trans>
        </Link>
      </BreadcrumbTextContent>
    </Breadcrumb>
  ];

  return (
    <Page.Header.Breadcrumbs iconID={ProductIcons.Graph} breadcrumbs={crumbs} />
  );
};

var DashboardPage = createReactClass({
  displayName: "DashboardPage",

  mixins: [InternalStorageMixin, StoreMixin],

  statics: {
    routeConfig: {
      label: i18nMark("Dashboard"),
      icon: <Icon shape={ProductIcons.GraphInverse} size={iconSizeS} />,
      matches: /^\/dashboard/
    },

    // Static life cycle method from react router, that will be called
    // 'when a handler is about to render', i.e. on route change:
    // https://github.com/rackt/react-router/
    // blob/master/docs/api/components/RouteHandler.md
    willTransitionTo() {
      SidebarActions.close();
    }
  },

  contextTypes: {
    router: routerShape
  },

  getDefaultProps() {
    return {
      componentsListLength: 5,
      servicesListLength: 5
    };
  },

  getInitialState() {
    return {
      dcosServices: [],
      unitHealthUnits: new HealthUnitsList({ items: [] })
    };
  },

  componentWillMount() {
    this.store_listeners = [
      { name: "dcos", events: ["change"], suppressUpdate: true },
      { name: "summary", events: ["success", "error"], suppressUpdate: true },
      {
        name: "unitHealth",
        events: ["success", "error"],
        suppressUpdate: true
      }
    ];

    this.internalStorage_set({
      openServicePanel: false,
      openTaskPanel: false
    });
    this.internalStorage_update(getMesosState());
  },

  onSummaryStoreError() {
    this.internalStorage_update(getMesosState());
  },

  onSummaryStoreSuccess() {
    this.internalStorage_update(getMesosState());
  },

  onDcosStoreChange() {
    this.setState({
      dcosServices: DCOSStore.serviceTree.getServices().getItems()
    });
  },

  onUnitHealthStoreSuccess() {
    this.setState({
      unitHealthUnits: UnitHealthStore.getUnits()
    });
  },

  onUnitHealthStoreError() {
    this.setState({
      unitHealthUnits: UnitHealthStore.getUnits()
    });
  },

  getServicesList() {
    const services = this.state.dcosServices;

    const sortedServices = services.sort(function(service, other) {
      const health = service.getHealth();
      const otherHealth = other.getHealth();

      return HealthSorting[health.key] - HealthSorting[otherHealth.key];
    });

    return sortedServices.slice(0, this.props.servicesListLength);
  },

  getUnits() {
    return this.state.unitHealthUnits;
  },

  getViewAllComponentsButton() {
    var componentCount = this.getUnits().getItems().length;
    if (!componentCount) {
      return null;
    }

    /* L10NTODO: Pluralize */<commit_msg>fix(Dashboard): service sort<commit_after>import { i18nMark } from "@lingui/react";
import { Trans } from "@lingui/macro";
import { routerShape, Link } from "react-router";
import React, { Suspense, lazy } from "react";
import createReactClass from "create-react-class";
import { StoreMixin } from "mesosphere-shared-reactjs";
import { Icon } from "@dcos/ui-kit";
import { ProductIcons } from "@dcos/ui-kit/dist/packages/icons/dist/product-icons-enum";
import { iconSizeS } from "@dcos/ui-kit/dist/packages/design-tokens/build/js/designTokens";

import DCOSStore from "#SRC/js/stores/DCOSStore";
import ResourcesUtil from "#SRC/js/utils/ResourcesUtil";

import Breadcrumb from "../components/Breadcrumb";
import Loader from "../components/Loader";
import BreadcrumbTextContent from "../components/BreadcrumbTextContent";
import ComponentList from "../components/ComponentList";
import Config from "../config/Config";
import InternalStorageMixin from "../mixins/InternalStorageMixin";
import MesosSummaryStore from "../stores/MesosSummaryStore";
import Page from "../components/Page";
import Panel from "../components/Panel";
import ServiceList from "../../../plugins/services/src/js/components/ServiceList";
import StringUtil from "../utils/StringUtil";
import SidebarActions from "../events/SidebarActions";
import UnitHealthStore from "../stores/UnitHealthStore";
import DashboardHeadings from "../constants/DashboardHeadings";
import HealthUnitsList from "../structs/HealthUnitsList";

function getMesosState() {
  const states = MesosSummaryStore.get("states");
  const last = states.lastSuccessful();

  return {
    activeNodes: states.getActiveNodesByState(),
    hostCount: last.getActiveSlaves().length,
    usedResourcesStates: states.getResourceStatesForNodeIDs(),
    usedResources: last.getSlaveUsedResources(),
    tasks: last.getServiceList().sumTaskStates(),
    totalResources: last.getSlaveTotalResources()
  };
}

const ResourceTimeSeriesChart = lazy(() =>
  import(/* webpackChunkName: "resourcetimeserieschart" */ "../components/charts/ResourceTimeSeriesChart")
);
const HostTimeSeriesChart = lazy(() =>
  import(/* webpackChunkName: "hosttimeserieschart" */ "../components/charts/HostTimeSeriesChart")
);
const TasksChart = lazy(() =>
  import(/* webpackChunkName: "taskschart" */ "../components/charts/TasksChart")
);

const DashboardBreadcrumbs = () => {
  const crumbs = [
    <Breadcrumb key={0} title="Dashboard">
      <BreadcrumbTextContent>
        <Link to="/dashboard">
          <Trans render="span">Dashboard</Trans>
        </Link>
      </BreadcrumbTextContent>
    </Breadcrumb>
  ];

  return (
    <Page.Header.Breadcrumbs iconID={ProductIcons.Graph} breadcrumbs={crumbs} />
  );
};

var DashboardPage = createReactClass({
  displayName: "DashboardPage",

  mixins: [InternalStorageMixin, StoreMixin],

  statics: {
    routeConfig: {
      label: i18nMark("Dashboard"),
      icon: <Icon shape={ProductIcons.GraphInverse} size={iconSizeS} />,
      matches: /^\/dashboard/
    },

    // Static life cycle method from react router, that will be called
    // 'when a handler is about to render', i.e. on route change:
    // https://github.com/rackt/react-router/
    // blob/master/docs/api/components/RouteHandler.md
    willTransitionTo() {
      SidebarActions.close();
    }
  },

  contextTypes: {
    router: routerShape
  },

  getDefaultProps() {
    return {
      componentsListLength: 5,
      servicesListLength: 5
    };
  },

  getInitialState() {
    return {
      dcosServices: [],
      unitHealthUnits: new HealthUnitsList({ items: [] })
    };
  },

  componentWillMount() {
    this.store_listeners = [
      { name: "dcos", events: ["change"], suppressUpdate: true },
      { name: "summary", events: ["success", "error"], suppressUpdate: true },
      {
        name: "unitHealth",
        events: ["success", "error"],
        suppressUpdate: true
      }
    ];

    this.internalStorage_set({
      openServicePanel: false,
      openTaskPanel: false
    });
    this.internalStorage_update(getMesosState());
  },

  onSummaryStoreError() {
    this.internalStorage_update(getMesosState());
  },

  onSummaryStoreSuccess() {
    this.internalStorage_update(getMesosState());
  },

  onDcosStoreChange() {
    this.setState({
      dcosServices: DCOSStore.serviceTree.getServices().getItems()
    });
  },

  onUnitHealthStoreSuccess() {
    this.setState({
      unitHealthUnits: UnitHealthStore.getUnits()
    });
  },

  onUnitHealthStoreError() {
    this.setState({
      unitHealthUnits: UnitHealthStore.getUnits()
    });
  },

  getServicesList() {
    const services = this.state.dcosServices;

    const sortedServices = services.sort(function(firstService, secondService) {
      const firstStatus = firstService.getServiceStatus();
      const secondStatus = secondService.getServiceStatus();

      // We invert this, since we want to show the highest priorities last.
      return secondStatus.priority - firstStatus.priority;
    });

    return sortedServices.slice(0, this.props.servicesListLength);
  },

  getUnits() {
    return this.state.unitHealthUnits;
  },

  getViewAllComponentsButton() {
    var componentCount = this.getUnits().getItems().length;
    if (!componentCount) {
      return null;
    }

    /* L10NTODO: Pluralize */
{'fraction_non_alphanumeric': 0.1392894166431062, 'fraction_numerical': 0.0018848364904344547, 'mean_word_length': 3.782334384858044, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 31, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5499727', 'n_tokens_mistral': 3160, 'n_tokens_neox': 3143, 'n_words': 628}