<commit_before>import { Button, Callout } from "@blueprintjs/core"
import styled from "@emotion/styled"
import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions"
import API from "api"
import { gql } from "apollo-boost"
import { LocationOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow"
import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect"
import { customFieldsJSONString } from "components/CustomFields"
import LocationField from "components/MergeField"
import Messages from "components/Messages"
import {
  CUSTOM_FIELD_TYPE_DEFAULTS,
  DEFAULT_CUSTOM_FIELDS_PARENT,
  MODEL_TO_OBJECT_TYPE
} from "components/Model"
import {
  jumpToTop,
  mapPageDispatchersToProps,
  PageDispatchersPropType,
  useBoilerplate
} from "components/Page"
import useMergeObjects, {
  getActionButton,
  getActivationButton,
  getClearButton,
  getInfoButton,
  selectAllFields,
  setAMergedField,
  setMergeable
} from "mergeUtils"
import { Location } from "models"
import PropTypes from "prop-types"
import React, { useState } from "react"
import { Col, FormGroup, Grid, Row } from "react-bootstrap"
import { connect } from "react-redux"
import { useHistory } from "react-router-dom"
import LOCATIONS_ICON from "resources/locations.png"
import Settings from "settings"
import utils from "utils"
import { areAllSet } from "../../mergeUtils"
import ApprovalSteps from "../locations/ApprovalSteps"

const GQL_MERGE_LOCATION = gql`
  mutation($loserUuid: String!, $winnerLocation: LocationInput!) {
    mergeLocations(loserUuid: $loserUuid, winnerLocation: $winnerLocation) {
      uuid
    }
  }
`

const MergeLocations = ({ pageDispatchers }) => {
  const history = useHistory()
  const [saveError, setSaveError] = useState(null)
  const [mergeState, dispatchMergeActions, mergeSides] = useMergeObjects(
    MODEL_TO_OBJECT_TYPE.Location
  )

  useBoilerplate({
    pageProps: PAGE_PROPS_NO_NAV,
    searchProps: DEFAULT_SEARCH_PROPS,
    pageDispatchers
  })

  const location1 = mergeState[mergeSides[0]]
  const location2 = mergeState[mergeSides[1]]
  const mergedLocation = mergeState.merged

  return (
    <Grid fluid>
      <Row>
        <Messages error={saveError} />

Merge Locations Tool

      </Row>
      <Row>
        <Col md={4} id="left-merge-loc-col">
          <LocationColumn
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
            align={mergeSides[0]}
            label="Location 1"
          >
          </LocationColumn>
        </Col>
        <Col md={4} id="mid-merge-loc-col">
          <MidColTitle>
            {getActionButton(
              () =>
                dispatchMergeActions(selectAllFields(location1, mergeSides[0])),
              mergeSides[0],
              mergeState,
              null,
              !areAllSet(location1, location2),
              "Use All"
            )}

Merged Location

            {getActionButton(
              () =>
                dispatchMergeActions(selectAllFields(location2, mergeSides[1])),
              mergeSides[1],
              mergeState,
              null,
              !areAllSet(location1, location2),
              "Use All"
            )}
          </MidColTitle>
          {!areAllSet(location1, location2) && (

              <Callout intent="warning">
                Please select both locations to proceed...
              </Callout>

          )}
          {areAllSet(location1, location2, mergedLocation) && (
            <>
              <LocationField
                label="Name"
                value={mergedLocation.name}
                align={"center"}
                action={getInfoButton("Name is required.")}
                fieldName="name"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Lattitude"
                fieldName="lat"
                value={mergedLocation.lat}
                action={getClearButton(() => {
                  dispatchMergeActions(setAMergedField("lat", null, null))
                  dispatchMergeActions(setAMergedField("lng", null, null))
                })}
                align={"center"}
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Longtitude"
                fieldName="lng"
                value={mergedLocation.lng}
                action={getClearButton(() => {
                  dispatchMergeActions(setAMergedField("lat", null, null))
                  dispatchMergeActions(setAMergedField("lng", null, null))
                })}
                align={"center"}
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Status"
                fieldName="status"
                value={mergedLocation.status}
                align={"center"}
                action={getActivationButton(
                  Location.isActive(mergedLocation),
                  () =>
                    dispatchMergeActions(
                      setAMergedField(
                        "status",
                        Location.isActive(mergedLocation)
                          ? Location.STATUS.INACTIVE
                          : Location.STATUS.ACTIVE,
                        null
                      )
                    ),
                  Location.getInstanceName
                )}
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Planning Approval Steps"
                fieldName="planningApprovalSteps"
                value={
                  <ApprovalSteps
                    approvalSteps={mergedLocation.planningApprovalSteps}
                  />
                }
                align="center"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Approval Steps"
                fieldName="approvalSteps"
                value={
                  <ApprovalSteps approvalSteps={mergedLocation.approvalSteps} />
                }
                align="center"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              {Settings.fields.location.customFields &&
                Object.entries(Settings.fields.location.customFields).map(
                  ([fieldName, fieldConfig]) => {
                    const fieldValue =
                      mergedLocation?.[DEFAULT_CUSTOM_FIELDS_PARENT]?.[
                        fieldName
                      ]
                    return (
                      <LocationField
                        key={fieldName}
                        label={fieldConfig.label || fieldName}
                        value={JSON.stringify(fieldValue)}
                        align="center"
                        action={getClearButton(() =>
                          dispatchMergeActions(
                            setAMergedField(
                              `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`,
                              CUSTOM_FIELD_TYPE_DEFAULTS[fieldConfig.type],
                              null
                            )
                          )
                        )}
                        fieldName={`${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`}
                        mergeState={mergeState}
                        dispatchMergeActions={dispatchMergeActions}
                      />
                    )
                  }
                )}
            </>
          )}
        </Col>
        <Col md={4} id="left-merge-loc-col">
          <LocationColumn
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
            align={mergeSides[1]}
            label="Location 2"
          >
          </LocationColumn>
        </Col>
      </Row>
      <Row>
        <Button
          style={{ width: "98%", margin: "16px 1%" }}
          large
          intent="primary"
          text="Merge Locations"
          onClick={mergeLocations}
          disabled={!areAllSet(location1, location2, mergedLocation?.name)}
        />
      </Row>
    </Grid>
  )

  function mergeLocations() {
    let loser
    if (mergedLocation.uuid) {
      loser = mergedLocation.uuid === location1.uuid ? location2 : location1
    } else {
      console.log("uuid not set")
    }
    mergedLocation.customFields = customFieldsJSONString(mergedLocation)

    const winnerLocation = Object.without(
      mergedLocation,
      "notes",
      "displayedCoordinate",
      DEFAULT_CUSTOM_FIELDS_PARENT
    )
    API.mutation(GQL_MERGE_LOCATION, {
      loserUuid: loser.uuid,
      winnerLocation
    })
      .then(res => {
        if (res.mergeLocations) {
          history.push(Location.pathFor({ uuid: res.mergeLocations.uuid }), {
            success: "Locations merged. Displaying merged Location below."
          })
        }
      })
      .catch(error => {
        setSaveError(error)
        jumpToTop()
      })
  }
}

MergeLocations.propTypes = {
  pageDispatchers: PageDispatchersPropType
}

const MidColTitle = styled.div`
  display: flex;
  height: 39px;
  margin-top: 25px;
  margin-bottom: 15px;
  border-bottom: 1px solid #cccccc;
  border-top: 1px solid #cccccc;
  justify-content: space-between;
  align-items: center;
`

function getLocationFilters() {
  const locationFilters = {
    activeLocations: {
      label: "All locations"
    }
  }
  return locationFilters
}

const LocationColumn = ({ align, label, mergeState, dispatchMergeActions }) => {
  const location = mergeState[align]
  const idForLocation = label.replace(/\s+/g, "")
  return (

      {label}
      <FormGroup controlId={idForLocation}>
        <AdvancedSingleSelect
          fieldName="location"
          fieldLabel="Select a location"
          placeholder="Select a location to merge"
          value={location}
          overlayColumns={["Name"]}
          overlayRenderRow={LocationOverlayRow}
          filterDefs={getLocationFilters()}
          onChange={value => {
            if (value?.customFields) {
              value[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe(
                value.customFields
              )
            }
            dispatchMergeActions(setMergeable(value, align))
          }}
          objectType={Location}
          valueKey="name"
          fields={Location.allFieldsQuery}
          addon={LOCATIONS_ICON}
          vertical
        >
        </AdvancedSingleSelect>
      </FormGroup>
      {areAllSet(location) && (
        <>
          <LocationField
            label="Name"
            fieldName="name"
            value={location.name}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("name", location.name, align)
                )
                dispatchMergeActions(
                  setAMergedField("uuid", location.uuid, align)
                )
              },
              align,
              mergeState,
              "name"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />

          <LocationField
            label="Lattitude"
            fieldName="lat"
            value={location.lat}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("lat", location.lat, align)
                )
                dispatchMergeActions(
                  setAMergedField("lng", location.lng, align)
                )
              },
              align,
              mergeState,
              "lat"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />

          <LocationField
            label="Longtitude"
            fieldName="lng"
            value={location.lng}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("lat", location.lat, align)
                )
                dispatchMergeActions(
                  setAMergedField("lng", location.lng, align)
                )
              },
              align,
              mergeState,
              "lng"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />

          <LocationField
            label="Status"
            fieldName="status"
            value={location.status}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("status", location.status, align)
                )
              },
              align,
              mergeState,
              "status"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          <LocationField
            label="Planning Approval Steps"
            fieldName="planningApprovalSteps"
            value={
              <ApprovalSteps approvalSteps={location.planningApprovalSteps} />
            }
            align={align}
            action={getActionButton(
              () =>
                dispatchMergeActions(
                  setAMergedField(
                    "planningApprovalSteps",
                    location.planningApprovalSteps,
                    align
                  )
                ),
              align,
              mergeState,
              "planningApprovalSteps"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          <LocationField
            label="Approval Steps"
            fieldName="approvalSteps"
            value={<ApprovalSteps approvalSteps={location.approvalSteps} />}
            align={align}
            action={getActionButton(
              () =>
                dispatchMergeActions(
                  setAMergedField(
                    "approvalSteps",
                    location.approvalSteps,
                    align
                  )
                ),
              align,
              mergeState,
              "approvalSteps"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          {Settings.fields.location.customFields &&
            Object.entries(Settings.fields.location.customFields).map(
              ([fieldName, fieldConfig]) => {
                const fieldValue =
                  location[DEFAULT_CUSTOM_FIELDS_PARENT][fieldName]
                return (
                  <LocationField
                    key={fieldName}
                    fieldName={`${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`}
                    label={fieldConfig.label || fieldName}
                    // To be able to see arrays and ojects
                    value={JSON.stringify(fieldValue)}
                    align={align}
                    action={getActionButton(
                      () =>
                        dispatchMergeActions(
                          setAMergedField(
                            `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`,
                            fieldValue,
                            align
                          )
                        ),
                      align,
                      mergeState,
                      `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`
                    )}
                    mergeState={mergeState}
                    dispatchMergeActions={dispatchMergeActions}
                  />
                )
              }
            )}
        </>
      )}

  )
}

LocationColumn.propTypes = {
  align: PropTypes.oneOf(["left", "right"]).isRequired,
  label: PropTypes.string.isRequired,
  mergeState: PropTypes.object,
  dispatchMergeActions: PropTypes.func
}

export default connect(null, mapPageDispatchersToProps)(MergeLocations)
<commit_msg>NCI-Agency/anet#2994: Add maps showing selected coordinates<commit_after>import { Button, Callout } from "@blueprintjs/core"
import styled from "@emotion/styled"
import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions"
import API from "api"
import { gql } from "apollo-boost"
import { LocationOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow"
import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect"
import { customFieldsJSONString } from "components/CustomFields"
import LocationField from "components/MergeField"
import Messages from "components/Messages"
import {
  CUSTOM_FIELD_TYPE_DEFAULTS,
  DEFAULT_CUSTOM_FIELDS_PARENT,
  MODEL_TO_OBJECT_TYPE
} from "components/Model"
import {
  jumpToTop,
  mapPageDispatchersToProps,
  PageDispatchersPropType,
  useBoilerplate
} from "components/Page"
import useMergeObjects, {
  getActionButton,
  getActivationButton,
  getClearButton,
  getInfoButton,
  getLeafletMap,
  selectAllFields,
  setAMergedField,
  setMergeable
} from "mergeUtils"
import { Location } from "models"
import PropTypes from "prop-types"
import React, { useState } from "react"
import { Col, FormGroup, Grid, Row } from "react-bootstrap"
import { connect } from "react-redux"
import { useHistory } from "react-router-dom"
import LOCATIONS_ICON from "resources/locations.png"
import Settings from "settings"
import utils from "utils"
import { convertLatLngToMGRS } from "../../geoUtils"
import { areAllSet } from "../../mergeUtils"
import ApprovalSteps from "../locations/ApprovalSteps"
import GeoLocation from "../locations/GeoLocation"

const GQL_MERGE_LOCATION = gql`
  mutation($loserUuid: String!, $winnerLocation: LocationInput!) {
    mergeLocations(loserUuid: $loserUuid, winnerLocation: $winnerLocation) {
      uuid
    }
  }
`

const MergeLocations = ({ pageDispatchers }) => {
  const history = useHistory()
  const [saveError, setSaveError] = useState(null)
  const [mergeState, dispatchMergeActions, mergeSides] = useMergeObjects(
    MODEL_TO_OBJECT_TYPE.Location
  )

  useBoilerplate({
    pageProps: PAGE_PROPS_NO_NAV,
    searchProps: DEFAULT_SEARCH_PROPS,
    pageDispatchers
  })

  const location1 = mergeState[mergeSides[0]]
  const location2 = mergeState[mergeSides[1]]
  const mergedLocation = mergeState.merged

  return (
    <Grid fluid>
      <Row>
        <Messages error={saveError} />

Merge Locations Tool

      </Row>
      <Row>
        <Col md={4} id="left-merge-loc-col">
          <LocationColumn
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
            align={mergeSides[0]}
            label="Location 1"
          >
          </LocationColumn>
        </Col>
        <Col md={4} id="mid-merge-loc-col">
          <MidColTitle>
            {getActionButton(
              () =>
                dispatchMergeActions(selectAllFields(location1, mergeSides[0])),
              mergeSides[0],
              mergeState,
              null,
              !areAllSet(location1, location2),
              "Use All"
            )}

Merged Location

            {getActionButton(
              () =>
                dispatchMergeActions(selectAllFields(location2, mergeSides[1])),
              mergeSides[1],
              mergeState,
              null,
              !areAllSet(location1, location2),
              "Use All"
            )}
          </MidColTitle>
          {!areAllSet(location1, location2) && (

              <Callout intent="warning">
                Please select both locations to proceed...
              </Callout>

          )}
          {areAllSet(location1, location2, mergedLocation) && (
            <>
              <LocationField
                label="Name"
                value={mergedLocation.name}
                align={"center"}
                action={getInfoButton("Name is required.")}
                fieldName="name"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Latitude, Longitude"
                fieldName="displayedCoordinate"
                value={
                  <GeoLocation
                    editable={false}
                    coordinates={{
                      lat: mergedLocation.lat,
                      lng: mergedLocation.lng,
                      displayedCoordinate: mergedLocation.displayedCoordinate
                    }}
                  />
                }
                action={getClearButton(() => {
                  dispatchMergeActions(
                    setAMergedField("displayedCoordinate", null, null)
                  )
                  dispatchMergeActions(setAMergedField("lat", null, null))
                  dispatchMergeActions(setAMergedField("lng", null, null))
                })}
                align={"center"}
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              {getLeafletMap("merged-location-map", mergedLocation)}
              <LocationField
                label="Status"
                fieldName="status"
                value={mergedLocation.status}
                align={"center"}
                action={getActivationButton(
                  Location.isActive(mergedLocation),
                  () =>
                    dispatchMergeActions(
                      setAMergedField(
                        "status",
                        Location.isActive(mergedLocation)
                          ? Location.STATUS.INACTIVE
                          : Location.STATUS.ACTIVE,
                        null
                      )
                    ),
                  Location.getInstanceName
                )}
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Planning Approval Steps"
                fieldName="planningApprovalSteps"
                value={
                  <ApprovalSteps
                    approvalSteps={mergedLocation.planningApprovalSteps}
                  />
                }
                align="center"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              <LocationField
                label="Approval Steps"
                fieldName="approvalSteps"
                value={
                  <ApprovalSteps approvalSteps={mergedLocation.approvalSteps} />
                }
                align="center"
                mergeState={mergeState}
                dispatchMergeActions={dispatchMergeActions}
              />
              {Settings.fields.location.customFields &&
                Object.entries(Settings.fields.location.customFields).map(
                  ([fieldName, fieldConfig]) => {
                    const fieldValue =
                      mergedLocation?.[DEFAULT_CUSTOM_FIELDS_PARENT]?.[
                        fieldName
                      ]
                    return (
                      <LocationField
                        key={fieldName}
                        label={fieldConfig.label || fieldName}
                        value={JSON.stringify(fieldValue)}
                        align="center"
                        action={getClearButton(() =>
                          dispatchMergeActions(
                            setAMergedField(
                              `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`,
                              CUSTOM_FIELD_TYPE_DEFAULTS[fieldConfig.type],
                              null
                            )
                          )
                        )}
                        fieldName={`${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`}
                        mergeState={mergeState}
                        dispatchMergeActions={dispatchMergeActions}
                      />
                    )
                  }
                )}
            </>
          )}
        </Col>
        <Col md={4} id="left-merge-loc-col">
          <LocationColumn
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
            align={mergeSides[1]}
            label="Location 2"
          >
          </LocationColumn>
        </Col>
      </Row>
      <Row>
        <Button
          style={{ width: "98%", margin: "16px 1%" }}
          large
          intent="primary"
          text="Merge Locations"
          onClick={mergeLocations}
          disabled={!areAllSet(location1, location2, mergedLocation?.name)}
        />
      </Row>
    </Grid>
  )

  function mergeLocations() {
    const loser = mergedLocation.uuid === location1.uuid ? location2 : location1
    mergedLocation.customFields = customFieldsJSONString(mergedLocation)

    const winnerLocation = Object.without(
      mergedLocation,
      "notes",
      "displayedCoordinate",
      DEFAULT_CUSTOM_FIELDS_PARENT
    )

    API.mutation(GQL_MERGE_LOCATION, {
      loserUuid: loser.uuid,
      winnerLocation
    })
      .then(res => {
        if (res.mergeLocations) {
          history.push(Location.pathFor({ uuid: res.mergeLocations.uuid }), {
            success: "Locations merged. Displaying merged Location below."
          })
        }
      })
      .catch(error => {
        setSaveError(error)
        jumpToTop()
      })
  }
}

MergeLocations.propTypes = {
  pageDispatchers: PageDispatchersPropType
}

const MidColTitle = styled.div`
  display: flex;
  height: 39px;
  margin-top: 25px;
  margin-bottom: 15px;
  border-bottom: 1px solid #cccccc;
  border-top: 1px solid #cccccc;
  justify-content: space-between;
  align-items: center;
`

function getLocationFilters() {
  const locationFilters = {
    activeLocations: {
      label: "All locations"
    }
  }
  return locationFilters
}

const LocationColumn = ({ align, label, mergeState, dispatchMergeActions }) => {
  const location = mergeState[align]
  const idForLocation = label.replace(/\s+/g, "")
  return (

      {label}
      <FormGroup controlId={idForLocation}>
        <AdvancedSingleSelect
          fieldName="location"
          fieldLabel="Select a location"
          placeholder="Select a location to merge"
          value={location}
          overlayColumns={["Name"]}
          overlayRenderRow={LocationOverlayRow}
          filterDefs={getLocationFilters()}
          onChange={value => {
            if (value?.customFields) {
              value[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe(
                value.customFields
              )
            }
            if (value) {
              value.displayedCoordinate = convertLatLngToMGRS(
                value.lat,
                value.lng
              )
            }
            dispatchMergeActions(setMergeable(value, align))
          }}
          objectType={Location}
          valueKey="name"
          fields={Location.allFieldsQuery}
          addon={LOCATIONS_ICON}
          vertical
        >
        </AdvancedSingleSelect>
      </FormGroup>
      {areAllSet(location) && (
        <>
          <LocationField
            label="Name"
            fieldName="name"
            value={location.name}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("name", location.name, align)
                )
                dispatchMergeActions(
                  setAMergedField("uuid", location.uuid, align)
                )
              },
              align,
              mergeState,
              "name"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />

          <LocationField
            label="Latitude, Longitude"
            fieldName="displayedCoordinate"
            value={
              <GeoLocation
                coordinates={{
                  lat: location.lat,
                  lng: location.lng,
                  displayedCoordinate: location.displayedCoordinate
                }}
              />
            }
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField(
                    "displayedCoordinate",
                    convertLatLngToMGRS(location.lat, location.lng),
                    align
                  )
                )
                dispatchMergeActions(
                  setAMergedField("lat", location.lat, align)
                )
                dispatchMergeActions(
                  setAMergedField("lng", location.lng, align)
                )
              },
              align,
              mergeState,
              "displayedCoordinate"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          {getLeafletMap(`merge-location-map-${align}`, location)}
          <LocationField
            label="Status"
            fieldName="status"
            value={location.status}
            align={align}
            action={getActionButton(
              () => {
                dispatchMergeActions(
                  setAMergedField("status", location.status, align)
                )
              },
              align,
              mergeState,
              "status"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          <LocationField
            label="Planning Approval Steps"
            fieldName="planningApprovalSteps"
            value={
              <ApprovalSteps approvalSteps={location.planningApprovalSteps} />
            }
            align={align}
            action={getActionButton(
              () =>
                dispatchMergeActions(
                  setAMergedField(
                    "planningApprovalSteps",
                    location.planningApprovalSteps,
                    align
                  )
                ),
              align,
              mergeState,
              "planningApprovalSteps"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          <LocationField
            label="Approval Steps"
            fieldName="approvalSteps"
            value={<ApprovalSteps approvalSteps={location.approvalSteps} />}
            align={align}
            action={getActionButton(
              () =>
                dispatchMergeActions(
                  setAMergedField(
                    "approvalSteps",
                    location.approvalSteps,
                    align
                  )
                ),
              align,
              mergeState,
              "approvalSteps"
            )}
            mergeState={mergeState}
            dispatchMergeActions={dispatchMergeActions}
          />
          {Settings.fields.location.customFields &&
            Object.entries(Settings.fields.location.customFields).map(
              ([fieldName, fieldConfig]) => {
                const fieldValue =
                  location[DEFAULT_CUSTOM_FIELDS_PARENT][fieldName]
                return (
                  <LocationField
                    key={fieldName}
                    fieldName={`${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`}
                    label={fieldConfig.label || fieldName}
                    // To be able to see arrays and ojects
                    value={JSON.stringify(fieldValue)}
                    align={align}
                    action={getActionButton(
                      () =>
                        dispatchMergeActions(
                          setAMergedField(
                            `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`,
                            fieldValue,
                            align
                          )
                        ),
                      align,
                      mergeState,
                      `${DEFAULT_CUSTOM_FIELDS_PARENT}.${fieldName}`
                    )}
                    mergeState={mergeState}
                    dispatchMergeActions={dispatchMergeActions}
                  />
                )
              }
            )}
        </>
      )}

  )
}

LocationColumn.propTypes = {
  align: PropTypes.oneOf(["left", "right"]).isRequired,
  label: PropTypes.string.isRequired,
  mergeState: PropTypes.object,
  dispatchMergeActions: PropTypes.func
}

export default connect(null, mapPageDispatchersToProps)(MergeLocations)
<|endoftext|>


<commit_before>var assert = require('assert');
var fs = require('fs');

var Address = require('../Address').class();
var PrivateKey = require('../PrivateKey').class();
var networks = require('../networks');
var KeyModule = require('../Key');
var coinUtil = require('../util/util');

suite('basic');

function test_encode_priv(b58, payload, isTestnet, isCompressed)
{
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = network.keySecret;

	var buf_pl = new Buffer(payload, 'hex');
	var buf;
	if (isCompressed) {
		buf = new Buffer(buf_pl.length + 1);
		buf_pl.copy(buf);
		buf[buf_pl.length] = 1;
	} else
		buf = buf_pl;

	var key = new KeyModule.Key();
	key.private = buf;
	key.compressed = isCompressed;

	var privkey = new PrivateKey(version, buf);
	assert.equal(privkey.toString(), b58);
}

function test_encode_pub(b58, payload, isTestnet, addrType)
{
	var isScript = (addrType == 'script');
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = isScript ? network.addressScript : network.addressPubkey;
	var buf = new Buffer(payload, 'hex');
	var addr = new Address(version, buf);
	assert.equal(addr.toString(), b58);
}

function test_decode_priv(b58, payload, isTestnet, isCompressed)
{
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = network.keySecret;

	var buf_pl = new Buffer(payload, 'hex');
	var buf;
	if (isCompressed) {
		buf = new Buffer(buf_pl.length + 1);
		buf_pl.copy(buf);
		buf[buf_pl.length] = 1;
	} else
		buf = buf_pl;

	var privkey = new PrivateKey(b58);
	assert.equal(version, privkey.version());
	assert.equal(buf.toString(), privkey.payload().toString());
}

function test_decode_pub(b58, payload, isTestnet, addrType)
{
	var isScript = (addrType == 'script');
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = isScript ? network.addressScript : network.addressPubkey;
	var buf = new Buffer(payload, 'hex');
	var addr = new Address(b58);

	assert.equal(version, addr.version());
	assert.equal(buf.toString(), addr.payload().toString());
}

function is_valid(datum)
{
	var b58 = datum[0];
	var payload = datum[1];
	var obj = datum[2];
	var isPrivkey = obj['isPrivkey'];
	var isTestnet = obj['isTestnet'];

	if (isPrivkey) {
		var isCompressed = obj['isCompressed'];
		test_encode_priv(b58, payload, isTestnet, isCompressed);
		test_decode_priv(b58, payload, isTestnet, isCompressed);
	} else {
		var addrType = obj['addrType'];
		test_encode_pub(b58, payload, isTestnet, addrType);
		test_decode_pub(b58, payload, isTestnet, addrType);
	}
}

function is_invalid(datum)
{
	if (datum.length < 1)
		throw new Error("Bad test");

	// ignore succeeding elements, as comments
	var b58 = datum[0];
	var privkey = new PrivateKey(b58);
	var addr = new Address(b58);

	var valid = true;
	try {
		privkey.validate();
		addr.validate();
	} catch(e) {
		valid = false;
	}
	assert.equal(valid, false);
}

function test_value(datum)
{
	if (datum.length != 2)
		throw new Error("Bad test");

	var decimal = datum[0];
	var intStr = datum[1];

	var bn = coinUtil.parseValue(decimal);
	assert.notEqual(bn, undefined);
	assert.equal(bn.toString(), intStr);
}

var dataValid = JSON.parse(fs.readFileSync('test/base58_keys_valid.json'));
var dataInvalid = JSON.parse(fs.readFileSync('test/base58_keys_invalid.json'));
var dataValues = JSON.parse(fs.readFileSync('test/values.json'));

test('valid', function() {
	dataValid.forEach(function(datum) { is_valid(datum); });
});

test('invalid', function() {
	dataInvalid.forEach(function(datum) { is_invalid(datum); });
});

test('values', function() {
	dataValues.forEach(function(datum) { test_value(datum); });
});

<commit_msg>add description to tests<commit_after>var assert = require('assert');
var fs = require('fs');

var Address = require('../Address').class();
var PrivateKey = require('../PrivateKey').class();
var networks = require('../networks');
var KeyModule = require('../Key');
var coinUtil = require('../util/util');

suite('basic');

function test_encode_priv(b58, payload, isTestnet, isCompressed)
{
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = network.keySecret;

	var buf_pl = new Buffer(payload, 'hex');
	var buf;
	if (isCompressed) {
		buf = new Buffer(buf_pl.length + 1);
		buf_pl.copy(buf);
		buf[buf_pl.length] = 1;
	} else
		buf = buf_pl;

	var key = new KeyModule.Key();
	key.private = buf;
	key.compressed = isCompressed;

	var privkey = new PrivateKey(version, buf);
	assert.equal(privkey.toString(), b58);
}

function test_encode_pub(b58, payload, isTestnet, addrType)
{
	var isScript = (addrType == 'script');
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = isScript ? network.addressScript : network.addressPubkey;
	var buf = new Buffer(payload, 'hex');
	var addr = new Address(version, buf);
	assert.equal(addr.toString(), b58);
}

function test_decode_priv(b58, payload, isTestnet, isCompressed)
{
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = network.keySecret;

	var buf_pl = new Buffer(payload, 'hex');
	var buf;
	if (isCompressed) {
		buf = new Buffer(buf_pl.length + 1);
		buf_pl.copy(buf);
		buf[buf_pl.length] = 1;
	} else
		buf = buf_pl;

	var privkey = new PrivateKey(b58);
	assert.equal(version, privkey.version());
	assert.equal(buf.toString(), privkey.payload().toString());
}

function test_decode_pub(b58, payload, isTestnet, addrType)
{
	var isScript = (addrType == 'script');
	var network = isTestnet ? networks.testnet : networks.livenet;
	var version = isScript ? network.addressScript : network.addressPubkey;
	var buf = new Buffer(payload, 'hex');
	var addr = new Address(b58);

	assert.equal(version, addr.version());
	assert.equal(buf.toString(), addr.payload().toString());
}

function is_valid(datum)
{
	var b58 = datum[0];
	var payload = datum[1];
	var obj = datum[2];
	var isPrivkey = obj['isPrivkey'];
	var isTestnet = obj['isTestnet'];

	if (isPrivkey) {
		var isCompressed = obj['isCompressed'];
		test_encode_priv(b58, payload, isTestnet, isCompressed);
		test_decode_priv(b58, payload, isTestnet, isCompressed);
	} else {
		var addrType = obj['addrType'];
		test_encode_pub(b58, payload, isTestnet, addrType);
		test_decode_pub(b58, payload, isTestnet, addrType);
	}
}

function is_invalid(datum)
{
	if (datum.length < 1)
		throw new Error("Bad test");

	// ignore succeeding elements, as comments
	var b58 = datum[0];
	var privkey = new PrivateKey(b58);
	var addr = new Address(b58);

	var valid = true;
	try {
		privkey.validate();
		addr.validate();
	} catch(e) {
		valid = false;
	}
	assert.equal(valid, false);
}

function test_value(datum)
{
	if (datum.length != 2)
		throw new Error("Bad test");

	var decimal = datum[0];
	var intStr = datum[1];

	var bn = coinUtil.parseValue(decimal);
	assert.notEqual(bn, undefined);
	assert.equal(bn.toString(), intStr);
}

var dataValid = JSON.parse(fs.readFileSync('test/base58_keys_valid.json'));
var dataInvalid = JSON.parse(fs.readFileSync('test/base58_keys_invalid.json'));
var dataValues = JSON.parse(fs.readFileSync('test/values.json'));

describe('valid base58 keys', function(){
  test('valid', function() {
    dataValid.forEach(function(datum) { is_valid(datum); });
  });
});

describe('invalid base58 keys', function(){
  test('invalid', function() {
    dataInvalid.forEach(function(datum) { is_invalid(datum); });
  });
});

describe('floating point unit conversion to satoshis', function(){
  test('values', function() {
    dataValues.forEach(function(datum) { test_value(datum); });
  });
});

<|endoftext|>


<commit_before>curl(
	{ baseUrl: openhmis.url.resources },
	[
		openhmis.url.backboneBase + 'js/lib/jquery',
		openhmis.url.backboneBase + 'js/view/patient',
		openhmis.url.backboneBase + 'js/lib/i18n',
		openhmis.url.cashierBase + 'js/view/bill',
		openhmis.url.cashierBase + 'js/view/payment',
		openhmis.url.cashierBase + 'js/model/lineItem'
	],
	function($, openhmis, __) {
		var Screen = function() {
			this.billUuid = openhmis.getQueryStringParameter("billUuid");
			this.patientUuid = openhmis.getQueryStringParameter("patientUuid");

			this.patientView = new openhmis.PatientView();
			// Set up patient search selection handler
			openhmis.doSelectionHandler = this.patientView.takeRawPatient;

			var options = new openhmis.GenericModel([], {
				urlRoot: openhmis.url.page + openhmis.url.cashierBase + "options.json"
			});

			var self = this;
			options.fetch({ success: function(options, resp) {
				self.createBillView.call(self, options, resp);
			}});
		}

		/**
		 * createBillView
		 *
		 * Create the bill view, using specified options, then fetch data needed
		 * to populate the view.
		 *
		 * @param {Model} options A populated options model
		 */
		Screen.prototype.createBillView = function(options) {
			this.billView = new openhmis.BillView({
				roundToNearest: options.get("roundToNearest"),
				roundingMode: options.get("roundingMode")
			});
			var self = this;
			// If a bill is specified
			if (this.billUuid) {
				// Load the bill
				var bill = new openhmis.Bill({ uuid: this.billUuid });
				bill.fetch({
					silent: true,
					success: function(bill, resp) {
						self.setupBillViewWithBill.call(self, bill, resp);
					}
				});
			}
			// If a patient is specified
			else if (this.patientUuid) {
				var patient = new openhmis.Patient({ uuid: this.patientUuid });
				patient.fetch({
					silent: true,
					success: function(patient, resp) {
						self.setupBillViewWithPatient.call(self, patient, resp);
					}
				});
			}
			else {
				this.displayBillView.call(this);
			}
		}

		/*
		 * setupBillViewWithBill
		 *
		 * For setting up the BillView with an existing bill
		 *
		 * @param {Bill} bill An initialized openhmis.Bill model
		 */
		Screen.prototype.setupBillViewWithBill = function(bill) {
			this.billView.setBill(bill);
			this.patientView.model = new openhmis.Patient(bill.get("patient"));
			if (bill.get("billAdjusted")) {
				var self = this;
				bill.get("billAdjusted").fetch({
					success: function(billAdjusted, resp) {
						self.displayBillView();
					}
				});
			}
			else
				this.displayBillView();
			this.patientView.selectPatient(this.patientView.model, {silent:true});
		}

		/*
		 * setupBillViewWithPatient
		 *
		 * For setting up the BillView to be associated with a patient
		 *
		 * @param {Patient} patient An initialized openhmis.Patient model
		 */
		Screen.prototype.setupBillViewWithPatient = function(patient) {
			this.billView.bill.set("patient", patient);
			this.patientView.model = patient;
			this.displayBillView();
		}

		/*
		 * displayBillView
		 *
		 * Take care of putting together and rendering all the elements of the
		 * BillView.  Relies on initialized billView and patientView
		 */
		Screen.prototype.displayBillView = function() {
			var self = this;
			// Easy access to status enumeration
			var BillStatus = this.billView.bill.BillStatus;

			// Automatic receipt printing
			if (openhmis.getQueryStringParameter("print") === "true") {
				this.billView.printReceipt();
				$("#printReceipt").attr("disabled", "disabled");
			}

			// Patient View
			if (this.billView.bill.get("status") !== BillStatus.PENDING)
				this.patientView.readOnly = true;
			this.patientView.setElement($('#patient-view'));
			this.patientView.render();

			this.billView.on("save paid adjusted", function(bill) {
				window.location = openhmis.url.getPage("cashierBase") + 'bill.form?billUuid=' + bill.id;
			});
			this.billView.on("saveAndPrint", function(bill) {
				var url = openhmis.url.getPage("cashier") + 'bill.form?billUuid=' + bill.id;
				url = openhmis.addQueryStringParameter(url, "print=true");
				window.location = url;
			});
			this.billView.setElement($('#bill'));

			$saveButton = $('#saveBill');
			$postButton = $('#postBill');
			$printButton = $("#printReceipt");
			switch (this.billView.bill.get("status")) {
				case BillStatus.PENDING:
					$saveButton.val(__("Save Bill"));
					$saveButton.click(this.billView.saveBill);
					var confirmMsg = __("Are you sure you want to post this bill?");
					$postButton.click(function() { if (confirm(confirmMsg)) { self.billView.postBill() }});
					$postButton.show();
					$printButton.val(__("Post & Print"));
					$printButton.click(function() { if (confirm(confirmMsg)) { self.billView.postBill({ print: true }) }});
					$printButton.show();

					if (this.billView.bill.get("billAdjusted")) {
						adjustedBillView = new openhmis.BillAndPaymentsView({
							model: this.billView.bill.get("billAdjusted")
						});
						$("#patient-view").after(adjustedBillView.el).addClass("combineBoxes");
						adjustedBillView.render();
						$("#bill").appendTo(adjustedBillView.$el);
						this.billView.options.listTitle = __("Adjustments");
					}

					// Provide cash point select, if this option is enabled
					var $cashPointLi = $("li.cashPoint");
					if (!$cashPointLi.hasClass("timesheet") && !this.billView.bill.get("billAdjusted"))
						this.billView.setupCashPointForm($("li.cashPoint"));
					break;
				case BillStatus.POSTED:
				case BillStatus.PAID:
					$saveButton.val(__("Adjust Bill"));
					$saveButton.click(this.billView.adjustBill);
					$printButton.val(__("Print Receipt"));
					$printButton.click(function(event) {
						self.billView.printReceipt(event);
						$(this).attr("disabled", "disabled");
					});
					$printButton.show();
					break;
				case BillStatus.ADJUSTED:
					$saveButton.remove();
					break;
			}

			this.billView.render();

			if (this.billView.bill.get("status") === BillStatus.PENDING)
				this.billView.setupNewItem();

			this.patientView.on('selected', this.billView.patientSelected);
			this.patientView.on('editing', this.billView.blur);

			// Payment View
			var readOnly = !(this.billView.bill.get("status") == BillStatus.PENDING
							 || this.billView.bill.get("status") == BillStatus.POSTED);
			var paymentView = new openhmis.PaymentView({
				paymentCollection: this.billView.bill.get("payments"),
				processCallback: this.billView.processPayment,
				readOnly: readOnly
			});
			// Disable add event when the bill is saving to prevent
			// unsettling page drawing
			this.billView.on("save", function() { paymentView.model.off("add"); });
			paymentView.paymentCollection.on("remove", this.billView.updateTotals);
			paymentView.setElement($('#payment'));
			paymentView.render();

			this.billView.on("focusNext", paymentView.focus);

			window.onbeforeunload = function() {
				if (self.billView.bill.isUnsaved())
					return __("There are unsaved changes.");
				return null;
			}

			if (this.billView.bill.get("patient"))
				this.billView.focus();
			else
				$('#inputNode').focus();
		}

		$(document).ready(function() {
			if ($("#bill").length > 0)
				var screen = new Screen();
		});

		return Screen;
	}
);
<commit_msg>Fixed URL for receipt.<commit_after>curl(
	{ baseUrl: openhmis.url.resources },
	[
		openhmis.url.backboneBase + 'js/lib/jquery',
		openhmis.url.backboneBase + 'js/view/patient',
		openhmis.url.backboneBase + 'js/lib/i18n',
		openhmis.url.cashierBase + 'js/view/bill',
		openhmis.url.cashierBase + 'js/view/payment',
		openhmis.url.cashierBase + 'js/model/lineItem'
	],
	function($, openhmis, __) {
		var Screen = function() {
			this.billUuid = openhmis.getQueryStringParameter("billUuid");
			this.patientUuid = openhmis.getQueryStringParameter("patientUuid");

			this.patientView = new openhmis.PatientView();
			// Set up patient search selection handler
			openhmis.doSelectionHandler = this.patientView.takeRawPatient;

			var options = new openhmis.GenericModel([], {
				urlRoot: openhmis.url.page + openhmis.url.cashierBase + "options.json"
			});

			var self = this;
			options.fetch({ success: function(options, resp) {
				self.createBillView.call(self, options, resp);
			}});
		}

		/**
		 * createBillView
		 *
		 * Create the bill view, using specified options, then fetch data needed
		 * to populate the view.
		 *
		 * @param {Model} options A populated options model
		 */
		Screen.prototype.createBillView = function(options) {
			this.billView = new openhmis.BillView({
				roundToNearest: options.get("roundToNearest"),
				roundingMode: options.get("roundingMode")
			});
			var self = this;
			// If a bill is specified
			if (this.billUuid) {
				// Load the bill
				var bill = new openhmis.Bill({ uuid: this.billUuid });
				bill.fetch({
					silent: true,
					success: function(bill, resp) {
						self.setupBillViewWithBill.call(self, bill, resp);
					}
				});
			}
			// If a patient is specified
			else if (this.patientUuid) {
				var patient = new openhmis.Patient({ uuid: this.patientUuid });
				patient.fetch({
					silent: true,
					success: function(patient, resp) {
						self.setupBillViewWithPatient.call(self, patient, resp);
					}
				});
			}
			else {
				this.displayBillView.call(this);
			}
		}

		/*
		 * setupBillViewWithBill
		 *
		 * For setting up the BillView with an existing bill
		 *
		 * @param {Bill} bill An initialized openhmis.Bill model
		 */
		Screen.prototype.setupBillViewWithBill = function(bill) {
			this.billView.setBill(bill);
			this.patientView.model = new openhmis.Patient(bill.get("patient"));
			if (bill.get("billAdjusted")) {
				var self = this;
				bill.get("billAdjusted").fetch({
					success: function(billAdjusted, resp) {
						self.displayBillView();
					}
				});
			}
			else
				this.displayBillView();
			this.patientView.selectPatient(this.patientView.model, {silent:true});
		}

		/*
		 * setupBillViewWithPatient
		 *
		 * For setting up the BillView to be associated with a patient
		 *
		 * @param {Patient} patient An initialized openhmis.Patient model
		 */
		Screen.prototype.setupBillViewWithPatient = function(patient) {
			this.billView.bill.set("patient", patient);
			this.patientView.model = patient;
			this.displayBillView();
		}

		/*
		 * displayBillView
		 *
		 * Take care of putting together and rendering all the elements of the
		 * BillView.  Relies on initialized billView and patientView
		 */
		Screen.prototype.displayBillView = function() {
			var self = this;
			// Easy access to status enumeration
			var BillStatus = this.billView.bill.BillStatus;

			// Automatic receipt printing
			if (openhmis.getQueryStringParameter("print") === "true") {
				this.billView.printReceipt();
				$("#printReceipt").attr("disabled", "disabled");
			}

			// Patient View
			if (this.billView.bill.get("status") !== BillStatus.PENDING)
				this.patientView.readOnly = true;
			this.patientView.setElement($('#patient-view'));
			this.patientView.render();

			this.billView.on("save paid adjusted", function(bill) {
				window.location = openhmis.url.getPage("cashierBase") + 'bill.form?billUuid=' + bill.id;
			});
			this.billView.on("saveAndPrint", function(bill) {
				var url = openhmis.url.getPage("cashierBase") + 'bill.form?billUuid=' + bill.id;
				url = openhmis.addQueryStringParameter(url, "print=true");
				window.location = url;
			});
			this.billView.setElement($('#bill'));

			$saveButton = $('#saveBill');
			$postButton = $('#postBill');
			$printButton = $("#printReceipt");
			switch (this.billView.bill.get("status")) {
				case BillStatus.PENDING:
					$saveButton.val(__("Save Bill"));
					$saveButton.click(this.billView.saveBill);
					var confirmMsg = __("Are you sure you want to post this bill?");
					$postButton.click(function() { if (confirm(confirmMsg)) { self.billView.postBill() }});
					$postButton.show();
					$printButton.val(__("Post & Print"));
					$printButton.click(function() { if (confirm(confirmMsg)) { self.billView.postBill({ print: true }) }});
					$printButton.show();

					if (this.billView.bill.get("billAdjusted")) {
						adjustedBillView = new openhmis.BillAndPaymentsView({
							model: this.billView.bill.get("billAdjusted")
						});
						$("#patient-view").after(adjustedBillView.el).addClass("combineBoxes");
						adjustedBillView.render();
						$("#bill").appendTo(adjustedBillView.$el);
						this.billView.options.listTitle = __("Adjustments");
					}

					// Provide cash point select, if this option is enabled
					var $cashPointLi = $("li.cashPoint");
					if (!$cashPointLi.hasClass("timesheet") && !this.billView.bill.get("billAdjusted"))
						this.billView.setupCashPointForm($("li.cashPoint"));
					break;
				case BillStatus.POSTED:
				case BillStatus.PAID:
					$saveButton.val(__("Adjust Bill"));
					$saveButton.click(this.billView.adjustBill);
					$printButton.val(__("Print Receipt"));
					$printButton.click(function(event) {
						self.billView.printReceipt(event);
						$(this).attr("disabled", "disabled");
					});
					$printButton.show();
					break;
				case BillStatus.ADJUSTED:
					$saveButton.remove();
					break;
			}

			this.billView.render();

			if (this.billView.bill.get("status") === BillStatus.PENDING)
				this.billView.setupNewItem();

			this.patientView.on('selected', this.billView.patientSelected);
			this.patientView.on('editing', this.billView.blur);

			// Payment View
			var readOnly = !(this.billView.bill.get("status") == BillStatus.PENDING
							 || this.billView.bill.get("status") == BillStatus.POSTED);
			var paymentView = new openhmis.PaymentView({
				paymentCollection: this.billView.bill.get("payments"),
				processCallback: this.billView.processPayment,
				readOnly: readOnly
			});
			// Disable add event when the bill is saving to prevent
			// unsettling page drawing
			this.billView.on("save", function() { paymentView.model.off("add"); });
			paymentView.paymentCollection.on("remove", this.billView.updateTotals);
			paymentView.setElement($('#payment'));
			paymentView.render();

			this.billView.on("focusNext", paymentView.focus);

			window.onbeforeunload = function() {
				if (self.billView.bill.isUnsaved())
					return __("There are unsaved changes.");
				return null;
			}

			if (this.billView.bill.get("patient"))
				this.billView.focus();
			else
				$('#inputNode').focus();
		}

		$(document).ready(function() {
			if ($("#bill").length > 0)
				var screen = new Screen();
		});

		return Screen;
	}
);
<|endoftext|>


<commit_before>var EC = protractor.ExpectedConditions;

describe('con10t pages', function() {

    function click() {

        browser.waitForAngular();
        return element.all(by.css('.leaflet-control-zoom-in')).get(0).getText().click();
    }

    it('should contain markers on the grako_map page', function(done) {
        browser.get('/project/grako_map');

        click().then(click).then(click).then(click).then(click).then(function() {
            var marker = element(by.css('.leaflet-marker-icon'));
            browser.wait(EC.presenceOf(marker), 10000);
            expect(marker.isPresent()).toBe(true);
            done();
        })

    });

});

<commit_msg>fix map e2e test<commit_after>var EC = protractor.ExpectedConditions;

describe('con10t pages', function() {

    function click() {

        browser.waitForAngular();
        return element.all(by.css('.leaflet-control-zoom-in')).get(0).getText().click();
    }

    it('should contain markers on the grako_map page', function(done) {
        browser.get('/project/grako_map');

        click().then(click).then(click).then(click).then(click).then(function() {
            var marker = element(by.css('.awesome-marker'));
            browser.wait(EC.presenceOf(marker), 10000);
            expect(marker.isPresent()).toBe(true);
            done();
        })

    });

});

<|endoftext|>


<commit_before>(function (window) {
    window.FireworkPresets = [
            {
                name: "Default",
                options: new window.Fireworks.Options()
            }, {
                name: "Supersonic",
                options: new window.Fireworks.Options({
                    timerTotal: 46,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 1,
                    fireworkSpeed: 30,
                    fireworkAcceleration: 1.2,
                    fireworkTargetRadius: 8,
                    fireworkShowTarget: false,
                    particleTrailLength: 30,
                    particleCount: 300,
                    particleFriction: 1.01,
                    particleGravity: 0.4,
                    particleAlpha: 0.3
                })
            }, {
                name: "Rain effect",
                options: new window.Fireworks.Options({
                    timerTotal: 40,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 3,
                    fireworkShowTarget: false,
                    particleTrailLength: 7,
                    particleCount: 227,
                    particleGravity: 4.7
                })
            }, {
                name: "Inversed Gravity",
                options: new window.Fireworks.Options({
                    timerTotal: 140,
                    ctxLineWidth: 1,
                    ctxShadow: false,
                    fireworkSpeed: 5,
                    fireworkShowTarget: false,
                    particleTrailLength: 6,
                    particleCount: 154,
                    particleSpeedRange: [1, 37],
                    particleFriction: 0.81,
                    particleGravity: -3.1,
                    particleAlpha: 0.9,
                    particleDecayRange: [0.015, 0.025]
                })
            },
            {
                name: "Rocket Launcher",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 2,
                    timerTotal: 150,
                    fireworkTrailLength: 1,
                    fireworkSpeed: 1,
                    fireworkAcceleration: 1.07,
                    fireworkTargetRadius: 20,
                    particleTrailLength: 30,
                    particleCount: 140,
                    particleFriction: 0.99,
                    particleGravity: -0.5,
                    particleAlpha: 0.9
                })
            },
            {
                name: "New Year",
                options: new window.Fireworks.Options({
                    timerTotal: 20,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 4,
                    fireworkAcceleration: 1.07,
                    fireworkTargetRadius: 4,
                    particleTrailLength: 11,
                    particleCount: 78,
                    particleGravity: 0.2,
                    particleAlpha: 0.8
                })
            },
            {
                name: "Distortion",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 6,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 4,
                    fireworkAcceleration: 1.02,
                    fireworkShowTarget: false,
                    particleTrailLength: 1,
                    particleCount: 130,
                    particleFriction: 0.89,
                    particleGravity: 0.4,
                    particleAlpha: 0.7
                })
            },
            {
                name: "Exploding Star",
                options: new window.Fireworks.Options({
                    timerTotal: 150,
                    ctxLineWidth: 1,
                    ctxShadow: false,
                    fireworkTargetRadius: 4,
                    particleTrailLength: 14,
                    particleCount: 300,
                    particleFriction: 1,
                    particleGravity: 0.5,
                    particleAlpha: 0.7
                })
            },
            {
                name: "Super Nova",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 1,
                    fireworkTrailLength: 5,
                    fireworkSpeed: 4,
                    fireworkShowTarget: false,
                    particleTrailLength: 30,
                    particleCount: 101,
                    particleFriction: 1.14,
                    particleGravity: 8.2
                })
            },
            {
                name: "Custom",
                options: new window.Fireworks.Options()
            }
    ];
})(window);
<commit_msg>New effect created - Circle<commit_after>(function (window) {
    window.FireworkPresets = [
            {
                name: "Default",
                options: new window.Fireworks.Options()
            }, {
                name: "Supersonic",
                options: new window.Fireworks.Options({
                    timerTotal: 46,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 1,
                    fireworkSpeed: 30,
                    fireworkAcceleration: 1.2,
                    fireworkTargetRadius: 8,
                    fireworkShowTarget: false,
                    particleTrailLength: 30,
                    particleCount: 300,
                    particleFriction: 1.01,
                    particleGravity: 0.4,
                    particleAlpha: 0.3
                })
            }, {
                name: "Rain effect",
                options: new window.Fireworks.Options({
                    timerTotal: 40,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 3,
                    fireworkShowTarget: false,
                    particleTrailLength: 7,
                    particleCount: 227,
                    particleGravity: 4.7
                })
            }, {
                name: "Inversed Gravity",
                options: new window.Fireworks.Options({
                    timerTotal: 140,
                    ctxLineWidth: 1,
                    ctxShadow: false,
                    fireworkSpeed: 5,
                    fireworkShowTarget: false,
                    particleTrailLength: 6,
                    particleCount: 154,
                    particleSpeedRange: [1, 37],
                    particleFriction: 0.81,
                    particleGravity: -3.1,
                    particleAlpha: 0.9,
                    particleDecayRange: [0.015, 0.025]
                })
            },
            {
                name: "Rocket Launcher",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 2,
                    timerTotal: 150,
                    fireworkTrailLength: 1,
                    fireworkSpeed: 1,
                    fireworkAcceleration: 1.07,
                    fireworkTargetRadius: 20,
                    particleTrailLength: 30,
                    particleCount: 140,
                    particleFriction: 0.99,
                    particleGravity: -0.5,
                    particleAlpha: 0.9
                })
            },
            {
                name: "New Year",
                options: new window.Fireworks.Options({
                    timerTotal: 20,
                    ctxLineWidth: 1,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 4,
                    fireworkAcceleration: 1.07,
                    fireworkTargetRadius: 4,
                    particleTrailLength: 11,
                    particleCount: 78,
                    particleGravity: 0.2,
                    particleAlpha: 0.8
                })
            },
            {
                name: "Distortion",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 6,
                    fireworkTrailLength: 2,
                    fireworkSpeed: 4,
                    fireworkAcceleration: 1.02,
                    fireworkShowTarget: false,
                    particleTrailLength: 1,
                    particleCount: 130,
                    particleFriction: 0.89,
                    particleGravity: 0.4,
                    particleAlpha: 0.7
                })
            },
            {
                name: "Exploding Star",
                options: new window.Fireworks.Options({
                    timerTotal: 150,
                    ctxLineWidth: 1,
                    ctxShadow: false,
                    fireworkTargetRadius: 4,
                    particleTrailLength: 14,
                    particleCount: 300,
                    particleFriction: 1,
                    particleGravity: 0.5,
                    particleAlpha: 0.7
                })
            }, {
                name: "Circle Path",
                options: new window.Fireworks.Options({
                    timerTotal:103,
                    ctxLineWidth:1,
                    ctxShadow:false,
                    fireworkTrailLength:1,
                    fireworkSpeed:7,
                    fireworkTargetRadius:20,
                    particleTrailLength:11,
                    particleCount:239,
                    particleSpeedRange: [1,1],
                    particleFriction:1.01,
                    particleGravity:-0.1,
                    particleDecayRange: [0.015,0.01]
                })

            }, {
                name: "Super Nova",
                options: new window.Fireworks.Options({
                    ctxLineWidth: 1,
                    fireworkTrailLength: 5,
                    fireworkSpeed: 4,
                    fireworkShowTarget: false,
                    particleTrailLength: 30,
                    particleCount: 101,
                    particleFriction: 1.14,
                    particleGravity: 8.2
                })
            },
            {
                name: "Custom",
                options: new window.Fireworks.Options()
            }
    ];
})(window);
<|endoftext|>


<commit_before>// --
// Core.UI.RichTextEditor.js - provides all UI functions
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.UI.RichTextEditor.js,v 1.13 2010-11-22 14:02:37 mn Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.UI = Core.UI || {};

/**
 * @namespace
 * @exports TargetNS as Core.UI.RichTextEditor
 * @description
 *      Richtext Editor
 * @requires
 *      CKEDITOR
 */
Core.UI.RichTextEditor = (function (TargetNS) {
    var $FormID;

    /**
     * @function
     * @private
     * @description Check in the window which hidden element has a name same to 'FormID' and return it like a JQuery object
     */
    function CheckFormID() {
        if (typeof $FormID === 'undefined') {
            $FormID = $('input:hidden[name=FormID]');
        }
        return $FormID;
    }

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that will be a rich text editor
     * @return nothing
     *      This function initializes the application and executes the needed functions
     */
    TargetNS.Init = function ($EditorArea) {
        var ToolbarSet = 'Simple',
            EditorID = '',
            Editor;
        if (CheckFormID().length) {
            ToolbarSet = 'Full';
        }

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        CKEDITOR.on('instanceCreated', function (Editor) {
            Editor.editor.addCss(Core.Config.Get('RichText.EditingAreaCSS'));
        });

        Editor = CKEDITOR.replace(EditorID,
        {
            customConfig: '', // avoid loading external config files
            defaultLanguage: Core.Config.Get('UserLanguage'),
            language: Core.Config.Get('UserLanguage'),
            width: Core.Config.Get('RichText.Width') || 620,
            resize_minWidth: Core.Config.Get('RichText.Width') || 620,
            height: Core.Config.Get('RichText.Height') || 320,
            // disable builtin spellchecker.net pluging "scayt"
            removePlugins : 'elementspath,scayt,menubutton,contextmenu',
            skin: 'default',
            forcePasteAsPlainText: false,
            fontSize_sizes: '8px;10px;12px;16px;18px;20px;22px;24px;26px;28px;30px;',
            enterMode: CKEDITOR.ENTER_BR,
            shiftEnterMode: CKEDITOR.ENTER_BR,
            contentsLangDirection: Core.Config.Get('RichText.TextDir') ? Core.Config.Get('RichText.TextDir') : 'ltr',
            disableNativeSpellChecker: false,
            toolbar_Full: Core.Config.Get('RichText.ToolbarFull'),
            toolbar_Simple: Core.Config.Get('RichText.ToolbarSimple'),
            toolbar: ToolbarSet,
            filebrowserUploadUrl: Core.Config.Get('Baselink'),
            extraPlugins: Core.Config.Get('RichText.SpellChecker') ? 'aspell' : ''
        });
        if (CheckFormID().length) {
            CKEDITOR.config.action = (Core.Config.Get('RichText.PictureUploadAction').length) ? Core.Config.Get('RichText.PictureUploadAction') : 'PictureUpload';
            CKEDITOR.config.formID = CheckFormID().val();
        }
        CKEDITOR.config.spellerPagesServerScript = Core.Config.Get('Baselink');

        // Hack for updating the textarea with the RTE content (bug#5857)
        // Rename the original function to another name, than overwrite the original one
        CKEDITOR.instances[EditorID].updateElementOriginal = CKEDITOR.instances[EditorID].updateElement;
        CKEDITOR.instances[EditorID].updateElement = function() {
            // Additional function that should be called if an element is updated
            function StripContent() {
                var Element = this.element,
                    Data = this.getData(),
                    StrippedContent = '';

                if (this.config.htmlEncodeOutput)
                    Data = CKEDITOR.tools.htmlEncode(Data);

                StrippedContent = Data.replace(/\s+| |<\/?\w+[^>]*\/?>/g, '');
                Data = (StrippedContent.length) ? Data : '';

                if (Element.is('textarea'))
                    Element.setValue(Data);
                else
                    Element.setHtml(Data);
            }

            // First call the original function
            CKEDITOR.instances[EditorID].updateElementOriginal();
            // Now call the new additional function on the same object
            StripContent.apply(CKEDITOR.instances[EditorID]);
        };

        // Needed for clientside validation of RTE
        CKEDITOR.instances[EditorID].on('blur', function () {
            CKEDITOR.instances[EditorID].updateElement();
            Core.Form.Validate.ValidateElement($EditorArea);
        });

        // mainly needed for clientside validation
        $EditorArea.focus(function () {
            TargetNS.Focus($EditorArea);
            Core.UI.ScrollTo($("label[for=" + $EditorArea.attr('id') + "]"));
        });
    };

    /**
     * @function
     * @return nothing
     *      This function initializes as a rich text editor every textarea element that containing the RichText class
     */
    TargetNS.InitAll = function () {
        $('textarea.RichText').each(function () {
            TargetNS.Init($(this));
        });
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return The rich text editor length
     *      This function return the length for a rich text editor object
     */
    TargetNS.GetRTE = function ($EditorArea) {
        if (isJQueryObject($EditorArea)) {
            var $RTE = $('#cke_' + $EditorArea.attr('id'));
            return ($RTE.length ? $RTE : undefined);
        }
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function updates the linked field for a rich text editor
     */
    TargetNS.UpdateLinkedField = function ($EditorArea) {
        var EditorID = '',
            Data,
            StrippedContent;

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        Data = CKEDITOR.instances[EditorID].getData();
        StrippedContent = Data.replace(/\s+| |<\/?\w+[^>]*\/?>/g, '');

        if (StrippedContent.length === 0) {
            $EditorArea.val('');
        }
        else {
            $EditorArea.val(Data);
        }
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function check if a rich text editor is enable in this moment
     */
    TargetNS.IsEnabled = function ($EditorArea) {
        var EditorID = '';

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
            if ($('#cke_' + EditorID).length) {
                return true;
            }
        }

        return false;
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function check if a rich text editor has the browser focus enabled
     */
    TargetNS.Focus = function ($EditorArea) {
        var EditorID = '';

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        if (typeof CKEDITOR === 'object') {
            CKEDITOR.instances[EditorID].focus();
        }
        else {
            $EditorArea.focus();
        }
    };

    return TargetNS;
}(Core.UI.RichTextEditor || {}));<commit_msg>Improved implementation, avoid code duplication.<commit_after>// --
// Core.UI.RichTextEditor.js - provides all UI functions
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.UI.RichTextEditor.js,v 1.14 2010-11-22 15:09:01 mg Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.UI = Core.UI || {};

/**
 * @namespace
 * @exports TargetNS as Core.UI.RichTextEditor
 * @description
 *      Richtext Editor
 * @requires
 *      CKEDITOR
 */
Core.UI.RichTextEditor = (function (TargetNS) {
    var $FormID;

    /**
     * @function
     * @private
     * @description Check in the window which hidden element has a name same to 'FormID' and return it like a JQuery object
     */
    function CheckFormID() {
        if (typeof $FormID === 'undefined') {
            $FormID = $('input:hidden[name=FormID]');
        }
        return $FormID;
    }

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that will be a rich text editor
     * @return nothing
     *      This function initializes the application and executes the needed functions
     */
    TargetNS.Init = function ($EditorArea) {
        var ToolbarSet = 'Simple',
            EditorID = '',
            Editor;
        if (CheckFormID().length) {
            ToolbarSet = 'Full';
        }

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        CKEDITOR.on('instanceCreated', function (Editor) {
            Editor.editor.addCss(Core.Config.Get('RichText.EditingAreaCSS'));
        });

        Editor = CKEDITOR.replace(EditorID,
        {
            customConfig: '', // avoid loading external config files
            defaultLanguage: Core.Config.Get('UserLanguage'),
            language: Core.Config.Get('UserLanguage'),
            width: Core.Config.Get('RichText.Width') || 620,
            resize_minWidth: Core.Config.Get('RichText.Width') || 620,
            height: Core.Config.Get('RichText.Height') || 320,
            // disable builtin spellchecker.net pluging "scayt"
            removePlugins : 'elementspath,scayt,menubutton,contextmenu',
            skin: 'default',
            forcePasteAsPlainText: false,
            fontSize_sizes: '8px;10px;12px;16px;18px;20px;22px;24px;26px;28px;30px;',
            enterMode: CKEDITOR.ENTER_BR,
            shiftEnterMode: CKEDITOR.ENTER_BR,
            contentsLangDirection: Core.Config.Get('RichText.TextDir') ? Core.Config.Get('RichText.TextDir') : 'ltr',
            disableNativeSpellChecker: false,
            toolbar_Full: Core.Config.Get('RichText.ToolbarFull'),
            toolbar_Simple: Core.Config.Get('RichText.ToolbarSimple'),
            toolbar: ToolbarSet,
            filebrowserUploadUrl: Core.Config.Get('Baselink'),
            extraPlugins: Core.Config.Get('RichText.SpellChecker') ? 'aspell' : ''
        });
        if (CheckFormID().length) {
            CKEDITOR.config.action = (Core.Config.Get('RichText.PictureUploadAction').length) ? Core.Config.Get('RichText.PictureUploadAction') : 'PictureUpload';
            CKEDITOR.config.formID = CheckFormID().val();
        }
        CKEDITOR.config.spellerPagesServerScript = Core.Config.Get('Baselink');

        // Hack for updating the textarea with the RTE content (bug#5857)
        // Rename the original function to another name, than overwrite the original one
        CKEDITOR.instances[EditorID].updateElementOriginal = CKEDITOR.instances[EditorID].updateElement;
        CKEDITOR.instances[EditorID].updateElement = function() {
            var Data;

            // First call the original function
            CKEDITOR.instances[EditorID].updateElementOriginal();

            // Now check if there is actually any non-whitespace content in the
            //  textarea field. If not, set it to an empty value to make sure
            //  the server side validation works correctly and there is no trash
            //  like '<br/>' stored in the DB.
            Data = this.element.getValue(); // get textarea content

            // remove tags and whitespace for checking
            Data = Data.replace(/\s+| |<\/?\w+[^>]*\/?>/g, '');
            if (!Data.length) {
                this.element.setValue(''); // reset textarea
            }
        };

        // Needed for clientside validation of RTE
        CKEDITOR.instances[EditorID].on('blur', function () {
            CKEDITOR.instances[EditorID].updateElement();
            Core.Form.Validate.ValidateElement($EditorArea);
        });

        // mainly needed for clientside validation
        $EditorArea.focus(function () {
            TargetNS.Focus($EditorArea);
            Core.UI.ScrollTo($("label[for=" + $EditorArea.attr('id') + "]"));
        });
    };

    /**
     * @function
     * @return nothing
     *      This function initializes as a rich text editor every textarea element that containing the RichText class
     */
    TargetNS.InitAll = function () {
        $('textarea.RichText').each(function () {
            TargetNS.Init($(this));
        });
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return The rich text editor length
     *      This function return the length for a rich text editor object
     */
    TargetNS.GetRTE = function ($EditorArea) {
        if (isJQueryObject($EditorArea)) {
            var $RTE = $('#cke_' + $EditorArea.attr('id'));
            return ($RTE.length ? $RTE : undefined);
        }
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function updates the linked field for a rich text editor
     */
    TargetNS.UpdateLinkedField = function ($EditorArea) {
        var EditorID = '',
            Data,
            StrippedContent;

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        Data = CKEDITOR.instances[EditorID].getData();
        StrippedContent = Data.replace(/\s+| |<\/?\w+[^>]*\/?>/g, '');

        if (StrippedContent.length === 0) {
            $EditorArea.val('');
        }
        else {
            $EditorArea.val(Data);
        }
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function check if a rich text editor is enable in this moment
     */
    TargetNS.IsEnabled = function ($EditorArea) {
        var EditorID = '';

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
            if ($('#cke_' + EditorID).length) {
                return true;
            }
        }

        return false;
    };

    /**
     * @function
     * @param {jQueryObject} $EditorArea The jQuery object of the element that is a rich text editor
     * @return nothing
     *      This function check if a rich text editor has the browser focus enabled
     */
    TargetNS.Focus = function ($EditorArea) {
        var EditorID = '';

        if (isJQueryObject($EditorArea) && $EditorArea.length === 1) {
            EditorID = $EditorArea.attr('id');
        }

        if (EditorID === '') {
            Core.Exception.Throw('RichTextEditor: Need exactly one EditorArea!', 'TypeError');
        }

        if (typeof CKEDITOR === 'object') {
            CKEDITOR.instances[EditorID].focus();
        }
        else {
            $EditorArea.focus();
        }
    };

    return TargetNS;
}(Core.UI.RichTextEditor || {}));<|endoftext|>