<commit_before>import { Settings } from "api"
import Model, {
  createYupObjectShape,
  NOTE_TYPE,
  yupDate
} from "components/Model"
import _isEmpty from "lodash/isEmpty"
import { Person, Position } from "models"
import moment from "moment"
import REPORTS_ICON from "resources/reports.png"
import utils from "utils"
import * as yup from "yup"

export default class Report extends Model {
  static resourceName = "Report"
  static listName = "reportList"
  static getInstanceName = "report"
  static getModelNameLinkTo = "report"

  static STATE = {
    DRAFT: "DRAFT",
    PENDING_APPROVAL: "PENDING_APPROVAL",
    APPROVED: "APPROVED",
    PUBLISHED: "PUBLISHED",
    REJECTED: "REJECTED",
    CANCELLED: "CANCELLED"
  }

  static ENGAGEMENT_STATUS = {
    HAPPENED: "HAPPENED",
    FUTURE: "FUTURE",
    CANCELLED: "CANCELLED"
  }

  static CANCELLATION_REASON = {
    CANCELLED_BY_ADVISOR: "CANCELLED_BY_ADVISOR",
    CANCELLED_BY_PRINCIPAL: "CANCELLED_BY_PRINCIPAL",
    CANCELLED_DUE_TO_TRANSPORTATION: "CANCELLED_DUE_TO_TRANSPORTATION",
    CANCELLED_DUE_TO_FORCE_PROTECTION: "CANCELLED_DUE_TO_FORCE_PROTECTION",
    CANCELLED_DUE_TO_ROUTES: "CANCELLED_DUE_TO_ROUTES",
    CANCELLED_DUE_TO_THREAT: "CANCELLED_DUE_TO_THREAT",
    CANCELLED_DUE_TO_AVAILABILITY_OF_INTERPRETERS:
      "CANCELLED_DUE_TO_AVAILABILITY_OF_INTERPRETERS"
  }

  static ATMOSPHERE = {
    POSITIVE: "POSITIVE",
    NEGATIVE: "NEGATIVE",
    NEUTRAL: "NEUTRAL"
  }

  // create yup schema for the customFields, based on the customFields config
  static customFieldsSchema = createYupObjectShape(
    Settings.fields.report.customFields
  )

  static yupSchema = yup
    .object()
    .shape({
      intent: yup
        .string()
        .nullable()
        .required(`You must provide the ${Settings.fields.report.intent}`)
        .default("")
        .label(Settings.fields.report.intent),
      engagementDate: yupDate
        .nullable()
        .required("You must provide the Date of Engagement")
        .default(null),
      duration: yup
        .number()
        .nullable()
        .default(null),
      // not actually in the database, but used for validation:
      cancelled: yup
        .boolean()
        .default(false)
        .label(Settings.fields.report.cancelled),
      cancelledReason: yup
        .string()
        .nullable()
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.required("You must provide a reason for cancellation")
            : schema.nullable()
        )
        .default(null),
      atmosphere: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "engagementDate"],
          (cancelled, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : !Report.isFuture(engagementDate)
                ? schema.required(
                  `You must provide the overall ${Settings.fields.report.atmosphere} of the engagement`
                )
                : schema.nullable()
        )
        .default(null)
        .label(Settings.fields.report.atmosphere),
      atmosphereDetails: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "atmosphere", "engagementDate"],
          (cancelled, atmosphere, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : !Report.isFuture(engagementDate)
                ? atmosphere === Report.ATMOSPHERE.POSITIVE
                  ? schema.nullable()
                  : schema.required(
                    `You must provide ${Settings.fields.report.atmosphereDetails} if the engagement was not Positive`
                  )
                : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.atmosphereDetails),
      location: yup
        .object()
        .nullable()
        .test(
          "location",
          "location error",
          // can't use arrow function here because of binding to 'this'
          function(location) {
            return _isEmpty(location)
              ? this.createError({ message: "You must provide the Location" })
              : true
          }
        )
        .default({}),
      attendees: yup
        .array()
        .nullable()
        .test(
          "primary-principal",
          "primary principal error",
          // can't use arrow function here because of binding to 'this'
          function(attendees) {
            const err = Report.checkPrimaryAttendee(
              attendees,
              Person.ROLE.PRINCIPAL
            )
            return err ? this.createError({ message: err }) : true
          }
        )
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.nullable()
            : schema.test(
              "primary-advisor",
              "primary advisor error",
              // can't use arrow function here because of binding to 'this'
              function(attendees) {
                const err = Report.checkPrimaryAttendee(
                  attendees,
                  Person.ROLE.ADVISOR
                )
                return err ? this.createError({ message: err }) : true
              }
            )
        )
        .default([]),
      principalOrg: yup
        .object()
        .nullable()
        .default({}),
      advisorOrg: yup
        .object()
        .nullable()
        .default({}),
      tasks: yup
        .array()
        .nullable()
        .test(
          "tasks",
          "tasks error",
          // can't use arrow function here because of binding to 'this'
          function(tasks) {
            return _isEmpty(tasks)
              ? this.createError({
                message: `You must provide at least one ${Settings.fields.task.shortLabel}`
              })
              : true
          }
        )
        .default([]),
      comments: yup
        .array()
        .nullable()
        .default([]),
      reportText: yup
        .string()
        .nullable()
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.nullable()
            : schema.test(
              "reportText",
              "reportText error",
              // can't use arrow function here because of binding to 'this'
              function(reportText) {
                return utils.isEmptyHtml(reportText)
                  ? this.createError({
                    message: `You must provide the ${Settings.fields.report.reportText}`
                  })
                  : true
              }
            )
        )
        .default("")
        .label(Settings.fields.report.reportText),
      nextSteps: yup
        .string()
        .when(["engagementDate"], (engagementDate, schema) =>
          !Report.isFuture(engagementDate)
            ? schema.required(
              `You must provide a brief summary of the ${Settings.fields.report.nextSteps}`
            )
            : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.nextSteps),
      keyOutcomes: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "engagementDate"],
          (cancelled, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : Settings.fields.report.keyOutcomes &&
                !Report.isFuture(engagementDate)
                ? schema.required(
                  `You must provide a brief summary of the ${Settings.fields.report.keyOutcomes}`
                )
                : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.keyOutcomes),
      tags: yup
        .array()
        .nullable()
        .default([]),
      reportTags: yup
        .array()
        .nullable()
        .default([])
        .label(Settings.fields.report.reportTags),
      reportSensitiveInformation: yup
        .object()
        .nullable()
        .default({}), // null?
      authorizationGroups: yup
        .array()
        .nullable()
        .default([]),
      // not actually in the database, the database contains the JSON customFields
      formCustomFields: Report.customFieldsSchema.nullable()
    })
    .concat(Model.yupSchema)

  static yupWarningSchema = yup.object().shape({
    reportSensitiveInformation: yup
      .object()
      .nullable()
      .default({}),
    authorizationGroups: yup
      .array()
      .nullable()
      .when(
        ["reportSensitiveInformation", "reportSensitiveInformation.text"],
        (reportSensitiveInformation, reportSensitiveInformationText, schema) =>
          _isEmpty(reportSensitiveInformation) ||
          _isEmpty(reportSensitiveInformationText)
            ? schema.nullable()
            : schema.required(`You should provide authorization groups who can access the sensitive information.
            If you do not do so, you will remain the only one authorized to see the sensitive information you have entered`)
      )
  })

  constructor(props) {
    super(Model.fillObject(props, Report.yupSchema))
  }

  static isDraft(state) {
    return state === Report.STATE.DRAFT
  }

  isDraft() {
    return Report.isDraft(this.state)
  }

  static isPending(state) {
    return state === Report.STATE.PENDING_APPROVAL
  }

  isPending() {
    return Report.isPending(this.state)
  }

  static isPublished(state) {
    return state === Report.STATE.PUBLISHED
  }

  isPublished() {
    return Report.isPublished(this.state)
  }

  static isRejected(state) {
    return state === Report.STATE.REJECTED
  }

  isRejected() {
    return Report.isRejected(this.state)
  }

  static isCancelled(state) {
    return state === Report.STATE.CANCELLED
  }

  isCancelled() {
    return Report.isCancelled(this.state)
  }

  static isFuture(engagementDate) {
    return (
      engagementDate &&
      moment()
        .endOf("day")
        .isBefore(engagementDate)
    )
  }

  isFuture() {
    return Report.isFuture(this.engagementDate)
  }

  static isApproved(state) {
    return state === Report.STATE.APPROVED
  }

  isApproved() {
    return Report.isApproved(this.state)
  }

  showWorkflow() {
    return this.state && !this.isDraft()
  }

  iconUrl() {
    return REPORTS_ICON
  }

  toString() {
    return this.intent || "None"
  }

  static checkPrimaryAttendee(attendees, role) {
    const primaryAttendee = Report.getPrimaryAttendee(attendees, role)
    const roleName = Person.humanNameOfRole(role)
    if (!primaryAttendee) {
      return `You must provide the primary ${roleName} for the Engagement`
    } else if (primaryAttendee.status !== Person.STATUS.ACTIVE) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to have an active profile`
    } else if (
      primaryAttendee.endOfTourDate &&
      moment(primaryAttendee.endOfTourDate).isBefore(moment().startOf("day"))
    ) {
      return `The primary ${roleName}'s - ${primaryAttendee.name} - end of tour date has passed`
    } else if (!primaryAttendee.position) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to be assigned to a position`
    } else if (primaryAttendee.position.status !== Position.STATUS.ACTIVE) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to be in an active position`
    }
  }

  static getPrimaryAttendee(attendees, role) {
    return attendees.find(el => el.role === role && el.primary)
  }

  static getEngagementDateFormat() {
    return Settings.engagementsIncludeTimeAndDuration
      ? Settings.dateFormats.forms.displayLong.withTime
      : Settings.dateFormats.forms.displayLong.date
  }

  getReportApprovedAt() {
    if (this.workflow && this.isApproved()) {
      const actions = Object.assign([], this.workflow)
      const lastApprovalStep = actions.pop()
      return !lastApprovalStep ? "" : lastApprovalStep.createdAt
    } else {
    }
  }

  getTaskAssessments() {
    const notesToAssessments = this.notes
      .filter(
        n =>
          n.type === NOTE_TYPE.ASSESSMENT &&
          n.noteRelatedObjects.filter(ro => ro.relatedObjectType === "tasks")
            .length
      )
      .map(ta => ({
        taskUuid: [
          ta.noteRelatedObjects.filter(
            ro => ro.relatedObjectType === "tasks"
          )[0].relatedObjectUuid
        ],
        assessmentUuid: ta.uuid,
        assessment: JSON.parse(ta.text)
      }))
    // When updating the assessments, we need for each task the uuid of the related assessment
    const taskToAssessmentUuid = {}
    // Get initial task assessments values
    const taskAssessments = {}
    notesToAssessments.forEach(ta => {
      taskToAssessmentUuid[ta.taskUuid] = ta.assessmentUuid
      taskAssessments[ta.taskUuid] = ta.assessment
    })
    return { taskToAssessmentUuid, taskAssessments }
  }
}
<commit_msg>Allow report to have an engagementDate yet a NULL nextSteps<commit_after>import { Settings } from "api"
import Model, {
  createYupObjectShape,
  NOTE_TYPE,
  yupDate
} from "components/Model"
import _isEmpty from "lodash/isEmpty"
import { Person, Position } from "models"
import moment from "moment"
import REPORTS_ICON from "resources/reports.png"
import utils from "utils"
import * as yup from "yup"

export default class Report extends Model {
  static resourceName = "Report"
  static listName = "reportList"
  static getInstanceName = "report"
  static getModelNameLinkTo = "report"

  static STATE = {
    DRAFT: "DRAFT",
    PENDING_APPROVAL: "PENDING_APPROVAL",
    APPROVED: "APPROVED",
    PUBLISHED: "PUBLISHED",
    REJECTED: "REJECTED",
    CANCELLED: "CANCELLED"
  }

  static ENGAGEMENT_STATUS = {
    HAPPENED: "HAPPENED",
    FUTURE: "FUTURE",
    CANCELLED: "CANCELLED"
  }

  static CANCELLATION_REASON = {
    CANCELLED_BY_ADVISOR: "CANCELLED_BY_ADVISOR",
    CANCELLED_BY_PRINCIPAL: "CANCELLED_BY_PRINCIPAL",
    CANCELLED_DUE_TO_TRANSPORTATION: "CANCELLED_DUE_TO_TRANSPORTATION",
    CANCELLED_DUE_TO_FORCE_PROTECTION: "CANCELLED_DUE_TO_FORCE_PROTECTION",
    CANCELLED_DUE_TO_ROUTES: "CANCELLED_DUE_TO_ROUTES",
    CANCELLED_DUE_TO_THREAT: "CANCELLED_DUE_TO_THREAT",
    CANCELLED_DUE_TO_AVAILABILITY_OF_INTERPRETERS:
      "CANCELLED_DUE_TO_AVAILABILITY_OF_INTERPRETERS"
  }

  static ATMOSPHERE = {
    POSITIVE: "POSITIVE",
    NEGATIVE: "NEGATIVE",
    NEUTRAL: "NEUTRAL"
  }

  // create yup schema for the customFields, based on the customFields config
  static customFieldsSchema = createYupObjectShape(
    Settings.fields.report.customFields
  )

  static yupSchema = yup
    .object()
    .shape({
      intent: yup
        .string()
        .nullable()
        .required(`You must provide the ${Settings.fields.report.intent}`)
        .default("")
        .label(Settings.fields.report.intent),
      engagementDate: yupDate
        .nullable()
        .required("You must provide the Date of Engagement")
        .default(null),
      duration: yup
        .number()
        .nullable()
        .default(null),
      // not actually in the database, but used for validation:
      cancelled: yup
        .boolean()
        .default(false)
        .label(Settings.fields.report.cancelled),
      cancelledReason: yup
        .string()
        .nullable()
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.required("You must provide a reason for cancellation")
            : schema.nullable()
        )
        .default(null),
      atmosphere: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "engagementDate"],
          (cancelled, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : !Report.isFuture(engagementDate)
                ? schema.required(
                  `You must provide the overall ${Settings.fields.report.atmosphere} of the engagement`
                )
                : schema.nullable()
        )
        .default(null)
        .label(Settings.fields.report.atmosphere),
      atmosphereDetails: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "atmosphere", "engagementDate"],
          (cancelled, atmosphere, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : !Report.isFuture(engagementDate)
                ? atmosphere === Report.ATMOSPHERE.POSITIVE
                  ? schema.nullable()
                  : schema.required(
                    `You must provide ${Settings.fields.report.atmosphereDetails} if the engagement was not Positive`
                  )
                : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.atmosphereDetails),
      location: yup
        .object()
        .nullable()
        .test(
          "location",
          "location error",
          // can't use arrow function here because of binding to 'this'
          function(location) {
            return _isEmpty(location)
              ? this.createError({ message: "You must provide the Location" })
              : true
          }
        )
        .default({}),
      attendees: yup
        .array()
        .nullable()
        .test(
          "primary-principal",
          "primary principal error",
          // can't use arrow function here because of binding to 'this'
          function(attendees) {
            const err = Report.checkPrimaryAttendee(
              attendees,
              Person.ROLE.PRINCIPAL
            )
            return err ? this.createError({ message: err }) : true
          }
        )
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.nullable()
            : schema.test(
              "primary-advisor",
              "primary advisor error",
              // can't use arrow function here because of binding to 'this'
              function(attendees) {
                const err = Report.checkPrimaryAttendee(
                  attendees,
                  Person.ROLE.ADVISOR
                )
                return err ? this.createError({ message: err }) : true
              }
            )
        )
        .default([]),
      principalOrg: yup
        .object()
        .nullable()
        .default({}),
      advisorOrg: yup
        .object()
        .nullable()
        .default({}),
      tasks: yup
        .array()
        .nullable()
        .test(
          "tasks",
          "tasks error",
          // can't use arrow function here because of binding to 'this'
          function(tasks) {
            return _isEmpty(tasks)
              ? this.createError({
                message: `You must provide at least one ${Settings.fields.task.shortLabel}`
              })
              : true
          }
        )
        .default([]),
      comments: yup
        .array()
        .nullable()
        .default([]),
      reportText: yup
        .string()
        .nullable()
        .when("cancelled", (cancelled, schema) =>
          cancelled
            ? schema.nullable()
            : schema.test(
              "reportText",
              "reportText error",
              // can't use arrow function here because of binding to 'this'
              function(reportText) {
                return utils.isEmptyHtml(reportText)
                  ? this.createError({
                    message: `You must provide the ${Settings.fields.report.reportText}`
                  })
                  : true
              }
            )
        )
        .default("")
        .label(Settings.fields.report.reportText),
      nextSteps: yup
        .string()
        .nullable()
        .when(["engagementDate"], (engagementDate, schema) =>
          !Report.isFuture(engagementDate)
            ? schema.required(
              `You must provide a brief summary of the ${Settings.fields.report.nextSteps}`
            )
            : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.nextSteps),
      keyOutcomes: yup
        .string()
        .nullable()
        .when(
          ["cancelled", "engagementDate"],
          (cancelled, engagementDate, schema) =>
            cancelled
              ? schema.nullable()
              : Settings.fields.report.keyOutcomes &&
                !Report.isFuture(engagementDate)
                ? schema.required(
                  `You must provide a brief summary of the ${Settings.fields.report.keyOutcomes}`
                )
                : schema.nullable()
        )
        .default("")
        .label(Settings.fields.report.keyOutcomes),
      tags: yup
        .array()
        .nullable()
        .default([]),
      reportTags: yup
        .array()
        .nullable()
        .default([])
        .label(Settings.fields.report.reportTags),
      reportSensitiveInformation: yup
        .object()
        .nullable()
        .default({}), // null?
      authorizationGroups: yup
        .array()
        .nullable()
        .default([]),
      // not actually in the database, the database contains the JSON customFields
      formCustomFields: Report.customFieldsSchema.nullable()
    })
    .concat(Model.yupSchema)

  static yupWarningSchema = yup.object().shape({
    reportSensitiveInformation: yup
      .object()
      .nullable()
      .default({}),
    authorizationGroups: yup
      .array()
      .nullable()
      .when(
        ["reportSensitiveInformation", "reportSensitiveInformation.text"],
        (reportSensitiveInformation, reportSensitiveInformationText, schema) =>
          _isEmpty(reportSensitiveInformation) ||
          _isEmpty(reportSensitiveInformationText)
            ? schema.nullable()
            : schema.required(`You should provide authorization groups who can access the sensitive information.
            If you do not do so, you will remain the only one authorized to see the sensitive information you have entered`)
      )
  })

  constructor(props) {
    super(Model.fillObject(props, Report.yupSchema))
  }

  static isDraft(state) {
    return state === Report.STATE.DRAFT
  }

  isDraft() {
    return Report.isDraft(this.state)
  }

  static isPending(state) {
    return state === Report.STATE.PENDING_APPROVAL
  }

  isPending() {
    return Report.isPending(this.state)
  }

  static isPublished(state) {
    return state === Report.STATE.PUBLISHED
  }

  isPublished() {
    return Report.isPublished(this.state)
  }

  static isRejected(state) {
    return state === Report.STATE.REJECTED
  }

  isRejected() {
    return Report.isRejected(this.state)
  }

  static isCancelled(state) {
    return state === Report.STATE.CANCELLED
  }

  isCancelled() {
    return Report.isCancelled(this.state)
  }

  static isFuture(engagementDate) {
    return (
      engagementDate &&
      moment()
        .endOf("day")
        .isBefore(engagementDate)
    )
  }

  isFuture() {
    return Report.isFuture(this.engagementDate)
  }

  static isApproved(state) {
    return state === Report.STATE.APPROVED
  }

  isApproved() {
    return Report.isApproved(this.state)
  }

  showWorkflow() {
    return this.state && !this.isDraft()
  }

  iconUrl() {
    return REPORTS_ICON
  }

  toString() {
    return this.intent || "None"
  }

  static checkPrimaryAttendee(attendees, role) {
    const primaryAttendee = Report.getPrimaryAttendee(attendees, role)
    const roleName = Person.humanNameOfRole(role)
    if (!primaryAttendee) {
      return `You must provide the primary ${roleName} for the Engagement`
    } else if (primaryAttendee.status !== Person.STATUS.ACTIVE) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to have an active profile`
    } else if (
      primaryAttendee.endOfTourDate &&
      moment(primaryAttendee.endOfTourDate).isBefore(moment().startOf("day"))
    ) {
      return `The primary ${roleName}'s - ${primaryAttendee.name} - end of tour date has passed`
    } else if (!primaryAttendee.position) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to be assigned to a position`
    } else if (primaryAttendee.position.status !== Position.STATUS.ACTIVE) {
      return `The primary ${roleName} - ${primaryAttendee.name} - needs to be in an active position`
    }
  }

  static getPrimaryAttendee(attendees, role) {
    return attendees.find(el => el.role === role && el.primary)
  }

  static getEngagementDateFormat() {
    return Settings.engagementsIncludeTimeAndDuration
      ? Settings.dateFormats.forms.displayLong.withTime
      : Settings.dateFormats.forms.displayLong.date
  }

  getReportApprovedAt() {
    if (this.workflow && this.isApproved()) {
      const actions = Object.assign([], this.workflow)
      const lastApprovalStep = actions.pop()
      return !lastApprovalStep ? "" : lastApprovalStep.createdAt
    } else {
    }
  }

  getTaskAssessments() {
    const notesToAssessments = this.notes
      .filter(
        n =>
          n.type === NOTE_TYPE.ASSESSMENT &&
          n.noteRelatedObjects.filter(ro => ro.relatedObjectType === "tasks")
            .length
      )
      .map(ta => ({
        taskUuid: [
          ta.noteRelatedObjects.filter(
            ro => ro.relatedObjectType === "tasks"
          )[0].relatedObjectUuid
        ],
        assessmentUuid: ta.uuid,
        assessment: JSON.parse(ta.text)
      }))
    // When updating the assessments, we need for each task the uuid of the related assessment
    const taskToAssessmentUuid = {}
    // Get initial task assessments values
    const taskAssessments = {}
    notesToAssessments.forEach(ta => {
      taskToAssessmentUuid[ta.taskUuid] = ta.assessmentUuid
      taskAssessments[ta.taskUuid] = ta.assessment
    })
    return { taskToAssessmentUuid, taskAssessments }
  }
}
<|endoftext|>


<commit_before>import { omit } from 'lodash';
import Raven from 'raven-js';

import * as auth from './auth';

const CONTENT_TYPE = {
  JSON: 'json',
};

const wrapUpdateToken = callback => auth.token().then(token => callback(token));

const iteratorToObject = (iterator) => {
  const result = {};
  iterator.forEach((value, key) => {
    result[key] = value;
  });
  return result;
};

const getContentType = (contentType) => {
  if (contentType.indexOf('application/json') > -1) {
    return CONTENT_TYPE.JSON;
  }
  return null;
};

const handleResponse = (response) => {
  const {
    ok,
    redirected,
    status,
    statusText,
    type,
    url,
    useFinalURL,
    bodyUsed,
  } = response;

  const headers = iteratorToObject(response.headers);
  const contentType = getContentType(headers['content-type']);

  if (!ok) {
    switch (status) {
      case 400: {
        return response.json().then((body) => {
          const error = new Error(`Bad request${body.message ? `: ${body.message}` : ''}`);
          Raven.captureException(error, {
            extra: {
              url,
              body,
              status,
            },
          });
          throw error;
        });
      }
      case 409: {
        return response.json().then((body) => {
          throw new Error(body.error);
        });
      }
      case 422: {
        return response.json().then((body) => {
          throw new Error(body.error.message);
        });
      }
      case 403: {
        return { status: 403, body: 'not authorized' };
      }
      case 401: {
        return { status: 401, body: 'not authenticated' };
      }
      case 404:
      case 500: {
        const error = new Error(statusText);
        Raven.captureException(error, {
          extra: {
            url,
            status,
          },
        });
        throw error;
      }
      default : {
        const error = new Error('There was an error communicating with the server.');
        Raven.captureException(error, {
          extra: {
            url,
            status,
          },
        });
        throw error;
      }
    }
  }

  switch (contentType) {
    case CONTENT_TYPE.JSON: {
      return response.json().then(body => ({
        headers,
        ok,
        redirected,
        status,
        statusText,
        type,
        url,
        useFinalURL,
        bodyUsed,
        body,
      }));
    }
    default: {
      return response;
    }
  }
};

const requestHeaders = (token, additionalHeaders = {}) => ({
  ...additionalHeaders,
  'Content-Type': 'application/json',
  Authorization: `Bearer ${token}`,
});

const getQueryString = queryParams =>
  Object.keys(queryParams).map((key, index) =>
    `${index > 0 ? '&' : ''}${key}=${encodeURIComponent(queryParams[key])}`
  ).join('');

export const get = (url, queryParams, headers) => {
  const urlWithOptionalParams = queryParams == null ? url : `${url}?${getQueryString(queryParams)}`;
  return wrapUpdateToken(token =>
    fetch(urlWithOptionalParams, {
      method: 'GET',
      headers: omit(requestHeaders(token, headers), 'Content-Type'),
    })
  )
  .then(handleResponse);
};

export const post = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'POST',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);

export const put = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'PUT',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);

export const del = (url, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'DELETE',
      headers: requestHeaders(token, headers),
    })
  )
  .then(handleResponse);

export const patch = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'PATCH',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);
<commit_msg>[#2379] Fix<commit_after>import { omit } from 'lodash';
import Raven from 'raven-js';
import * as auth from './auth';

require('isomorphic-fetch');

const CONTENT_TYPE = {
  JSON: 'json',
};

const wrapUpdateToken = callback => auth.token().then(token => callback(token));

const iteratorToObject = (iterator) => {
  const result = {};
  iterator.forEach((value, key) => {
    result[key] = value;
  });
  return result;
};

const getContentType = (contentType) => {
  if (contentType.indexOf('application/json') > -1) {
    return CONTENT_TYPE.JSON;
  }
  return null;
};

const handleResponse = (response) => {
  const {
    ok,
    redirected,
    status,
    statusText,
    type,
    url,
    useFinalURL,
    bodyUsed,
  } = response;

  const headers = iteratorToObject(response.headers);
  const contentType = getContentType(headers['content-type']);

  if (!ok) {
    switch (status) {
      case 400: {
        return response.json().then((body) => {
          const error = new Error(`Bad request${body.message ? `: ${body.message}` : ''}`);
          Raven.captureException(error, {
            extra: {
              url,
              body,
              status,
            },
          });
          throw error;
        });
      }
      case 409: {
        return response.json().then((body) => {
          throw new Error(body.error);
        });
      }
      case 422: {
        return response.json().then((body) => {
          throw new Error(body.error.message);
        });
      }
      case 403: {
        return { status: 403, body: 'not authorized' };
      }
      case 401: {
        return { status: 401, body: 'not authenticated' };
      }
      case 404:
      case 500: {
        const error = new Error(statusText);
        Raven.captureException(error, {
          extra: {
            url,
            status,
          },
        });
        throw error;
      }
      default : {
        const error = new Error('There was an error communicating with the server.');
        Raven.captureException(error, {
          extra: {
            url,
            status,
          },
        });
        throw error;
      }
    }
  }

  switch (contentType) {
    case CONTENT_TYPE.JSON: {
      return response.json().then(body => ({
        headers,
        ok,
        redirected,
        status,
        statusText,
        type,
        url,
        useFinalURL,
        bodyUsed,
        body,
      }));
    }
    default: {
      return response;
    }
  }
};

const requestHeaders = (token, additionalHeaders = {}) => ({
  ...additionalHeaders,
  'Content-Type': 'application/json',
  Authorization: `Bearer ${token}`,
});

const getQueryString = queryParams =>
  Object.keys(queryParams).map((key, index) =>
    `${index > 0 ? '&' : ''}${key}=${encodeURIComponent(queryParams[key])}`
  ).join('');

export const get = (url, queryParams, headers) => {
  const urlWithOptionalParams = queryParams == null ? url : `${url}?${getQueryString(queryParams)}`;
  return wrapUpdateToken(token =>
    fetch(urlWithOptionalParams, {
      method: 'GET',
      headers: omit(requestHeaders(token, headers), 'Content-Type'),
    })
  )
  .then(handleResponse);
};

export const post = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'POST',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);

export const put = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'PUT',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);

export const del = (url, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'DELETE',
      headers: requestHeaders(token, headers),
    })
  )
  .then(handleResponse);

export const patch = (url, body, headers) =>
  wrapUpdateToken(token =>
    fetch(url, {
      method: 'PATCH',
      headers: requestHeaders(token, headers),
      body: JSON.stringify(body),
    })
  )
  .then(handleResponse);
<|endoftext|>


<commit_before>Template.allgood.helpers({
  status: function() {
    var self = Template.instance();
    if (Session.get('easter egg counter') < 7) {
      return 'Jest dobrze.';
    } else if (self.taunts.length) {
      var randpos = Math.floor(Math.random() * self.taunts.length);
      return self.taunts.splice(randpos, 1)[0];
    } else {
      return 'Jest dużodobrze.';
    }
  },
});

function resetTaunts () {
  Session.set('easter egg counter', 0);
  this.taunts = taunts.slice();
}

Template.allgood.events({
  'click .nj-cover__ninja': function(event, self) {
    trackEvent('Fun', 'Allgood tap');
    var eggCounter = Session.get('easter egg counter');
    if (eggCounter < 15) {
      Session.set('easter egg counter', eggCounter + 1);
    } else {
      resetTaunts.call(self);
    }
  },
});

Template.allgood.onCreated(function() {
  resetTaunts.call(this);
});

Template.allgood.onRendered(function() {
  var ninja = this.find('.nj-cover__ninja');

  var transform;
  var timer;

  if (!ninja) {
    return false;
  }

  var mc = new Hammer.Manager(ninja);

  mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
  mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));
  mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);

  mc.on("panstart panmove", onPan);
  mc.on("pinchstart pinchmove", onPinch);

  mc.on("hammer.input", function(ev) {
    if (ev.isFinal) {
      resetElement();
    }
  });

  function resetElement() {
    ninja.classList.add('nj-cover__ninja--animated');
    transform = {
      translate: { x: 0, y: 0 },
      scale: 1,
      rotateX: 0,
      rotateY: 0,
    };
    window.requestAnimationFrame(updateElementTransform);
  }

  function updateElementTransform() {
    var value = [
      'translate3d(' + transform.translate.x + 'px, ' +
        transform.translate.y + 'px, 0)',
      'scale(' + transform.scale + ', ' + transform.scale + ')',
      'rotateX('+ transform.rotateX + 'deg)',
      'rotateY('+ transform.rotateY + 'deg)',
    ];

    value = value.join(" ");
    ninja.style.webkitTransform = value;
    ninja.style.mozTransform = value;
    ninja.style.transform = value;
  }

  var max = Math.min(window.innerWidth / 2, window.innerHeight / 2);

  function damp(x, max) {
    var abs = max * (1 - Math.exp(-0.005 * Math.abs(x)));
    return x > 0 ? abs : -abs;
  }

  function onPan(ev) {
    ninja.classList.remove('nj-cover__ninja--animated');
    transform.translate = {
      x: damp(ev.deltaX, max),
      y: damp(ev.deltaY, max)
    };

    transform.rotateX = - damp(ev.deltaY, 90);
    transform.rotateY = damp(ev.deltaX, 90);

    window.requestAnimationFrame(updateElementTransform);
  }

  var initScale = 1;
  function onPinch(ev) {
    if(ev.type == 'pinchstart') {
      initScale = transform.scale || 1;
    }

    ninja.classList.remove('nj-cover__ninja--animated');
    transform.scale = initScale * ev.scale;

    window.requestAnimationFrame(updateElementTransform);
  }

  resetElement();

});
<commit_msg>remove rotation from the all-good animation<commit_after>Template.allgood.helpers({
  status: function() {
    var self = Template.instance();
    if (Session.get('easter egg counter') < 7) {
      return 'Jest dobrze.';
    } else if (self.taunts.length) {
      var randpos = Math.floor(Math.random() * self.taunts.length);
      return self.taunts.splice(randpos, 1)[0];
    } else {
      return 'Jest dużodobrze.';
    }
  },
});

function resetTaunts () {
  Session.set('easter egg counter', 0);
  this.taunts = taunts.slice();
}

Template.allgood.events({
  'click .nj-cover__ninja': function(event, self) {
    trackEvent('Fun', 'Allgood tap');
    var eggCounter = Session.get('easter egg counter');
    if (eggCounter < 15) {
      Session.set('easter egg counter', eggCounter + 1);
    } else {
      resetTaunts.call(self);
    }
  },
});

Template.allgood.onCreated(function() {
  resetTaunts.call(this);
});

Template.allgood.onRendered(function() {
  var ninja = this.find('.nj-cover__ninja');

  var transform;
  var timer;

  if (!ninja) {
    return false;
  }

  var mc = new Hammer.Manager(ninja);

  mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
  mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));

  mc.on("panstart panmove", onPan);

  mc.on("hammer.input", function(ev) {
    if (ev.isFinal) {
      resetElement();
    }
  });

  function resetElement() {
    ninja.classList.add('nj-cover__ninja--animated');
    transform = {
      translate: { x: 0, y: 0 },
    };
    window.requestAnimationFrame(updateElementTransform);
  }

  function updateElementTransform() {
    var value = [
      'translate3d(' + transform.translate.x + 'px, ' +
        transform.translate.y + 'px, 0)',
    ];

    value = value.join(" ");
    ninja.style.webkitTransform = value;
    ninja.style.mozTransform = value;
    ninja.style.transform = value;
  }

  var max = Math.min(window.innerWidth / 2, window.innerHeight / 2);

  function damp(x, max) {
    var abs = max * (1 - Math.exp(-0.005 * Math.abs(x)));
    return x > 0 ? abs : -abs;
  }

  function onPan(ev) {
    ninja.classList.remove('nj-cover__ninja--animated');
    transform.translate = {
      x: damp(ev.deltaX, max),
      y: damp(ev.deltaY, max)
    };

    window.requestAnimationFrame(updateElementTransform);
  }

  resetElement();

});
<|endoftext|>


<commit_before>(function() {
  function Enigma() { }

  Enigma.prototype.GetValue = function(element) {
    return jQuery(element).attr('data-enigmav');
  };

  Enigma.prototype.Replace = function(element) {
    var value = this.GetValue(element);
    if (!value) {
      return;
    }
    jQuery(element).replaceWith(jQuery.parseJSON('"' + value + '"'));
  };

  Enigma.prototype.Clickable = function(element) {
    var thisEnigma = this;
    var link = jQuery("<a />", {
      href : "#",
      text : jQuery(element).text(),
      'data-enigmav' : this.GetValue(element)
    });
    jQuery(element).replaceWith(link);
    jQuery(link).on('click', function() {
      thisEnigma.Replace(link);
      return false;
    });
  };

  Enigma.prototype.IfReplied = function(element) {
    var pattern = /comment_author_[^=]*=([^;]+);/g;
    var cookie = document.cookie;
    var nameCap = [];
    var names = [];
    while ((nameCap = pattern.exec(cookie)) !== null) {
      names.push(nameCap[1]);
    }
    if (names.length === 0) {
      return;
    }
    var found = false;
    jQuery('*').each(function(idx, element) {
      var text = jQuery(element).text();
      for (var i = 0; i < names.length; ++i) {
        if (names[i] === text || decodeURIComponent(names[i]) === text) {
          found = true;
          break;
        }
      }
    });
    if (found) {
      this.Replace(element);
    }
  };

  Enigma.prototype.Run = function() {
    var thisEnigma = this;
    jQuery('span[id^="engimadiv"]').each(function(idx, element) {
      if (jQuery(element).attr('data-enigmad') === 'y') {
        return thisEnigma.Clickable(element);
      } else if (jQuery(element).attr('data-enigmad') === 'replied') {
        return thisEnigma.IfReplied(element);
      }
      thisEnigma.Replace(element);
    });
  };

  jQuery(function() {
    new Enigma().Run();
    setInterval(function() { new Enigma().Run();}, 2000);
  });
})();
<commit_msg>update<commit_after>(function() {
  function Enigma() { }

  Enigma.prototype.GetValue = function(element) {
    return jQuery(element).attr('data-enigmav');
  };

  Enigma.prototype.Replace = function(element) {
    var value = this.GetValue(element);
    if (!value) {
      return;
    }
    jQuery(element).replaceWith(jQuery.parseJSON('"' + value + '"'));
  };

  Enigma.prototype.Clickable = function(element) {
    var thisEnigma = this;
    var link = jQuery("<a />", {
      href : "#",
      text : jQuery(element).text(),
      'data-enigmav' : this.GetValue(element)
    });
    jQuery(element).replaceWith(link);
    jQuery(link).on('click', function() {
      thisEnigma.Replace(link);
      return false;
    });
  };

  Enigma.prototype.IfReplied = function(element) {
    var pattern = /comment_author_[^=]*=([^;]+);/g;
    var cookie = document.cookie;
    var nameCap = [];
    var names = {};
    while ((nameCap = pattern.exec(cookie)) !== null) {
      names[nameCap[1]] = true;
      var decodedName = decodeURIComponent(nameCap[1]);
      if (decodedName !== nameCap[1]) {
        names[decodedName] = true;
      }
    }
    if (jQuery.isEmptyObject(names)) {
      return;
    }
    var found = false;
    jQuery('*').each(function(idx, element) {
      var text = jQuery(element).text();
      if (names[text]) {
        found = true;
        return false;
      }
    });
    if (found) {
      this.Replace(element);
    }
  };

  Enigma.prototype.Run = function() {
    var thisEnigma = this;
    jQuery('span[id^="engimadiv"]').each(function(idx, element) {
      if (jQuery(element).attr('data-enigmad') === 'y') {
        return thisEnigma.Clickable(element);
      } else if (jQuery(element).attr('data-enigmad') === 'replied') {
        return thisEnigma.IfReplied(element);
      }
      thisEnigma.Replace(element);
    });
  };

  jQuery(function() {
    new Enigma().Run();
    setInterval(function() { new Enigma().Run();}, 2000);
  });
})();
<|endoftext|>


<commit_before>'use strict';
const path = require('path');

module.exports = {
	extends: path.join(__dirname, 'index.js'),
	rules: {
		'no-var': 'error',
		'object-shorthand': ['error', 'always'],
		'prefer-arrow-callback': 'error',
		'prefer-const': ['error', {
			destructuring: 'all'
		}],
		'prefer-numeric-literals': 2

		// Disabled since latest Node.js LTS doesn't yet support it
		// 'prefer-reflect': ['error', {exceptions: ['delete']}],

		// 'prefer-rest-params': 'error',

		// disabled because of https://github.com/eslint/eslint/issues/6572
		// 'prefer-template': 'error',

		// 'prefer-spread': 'error',
	}
};
<commit_msg>Add the `prefer-destructuring` rule commented out<commit_after>'use strict';
const path = require('path');

module.exports = {
	extends: path.join(__dirname, 'index.js'),
	rules: {
		'no-var': 'error',
		'object-shorthand': ['error', 'always'],
		'prefer-arrow-callback': 'error',
		'prefer-const': ['error', {
			destructuring: 'all'
		}],
		'prefer-numeric-literals': 2

		// Disabled since latest Node.js LTS doesn't yet support it
		// 'prefer-reflect': ['error', {exceptions: ['delete']}],
		// 'prefer-rest-params': 'error',
		// 'prefer-spread': 'error',
		// 'prefer-destructuring': ['error', {
		// 	array: true,
		// 	object: true
		// }, {
		// 	enforceForRenamedProperties: true
		// }]

		// Disabled because of https://github.com/eslint/eslint/issues/6572
		// 'prefer-template': 'error'
	}
};
<|endoftext|>


<commit_before>import template from './issue-registration.html';

export default function issueRegistration() {
  return {
    restrict: 'E',
    template: template,
    controller: IssueRegistrationController,
    controllerAs: '$ctrl',
    scope: {
      onSearch: '&'
    },
    bindToController: true
  };
}

// @ngInject
class IssueRegistrationController {
  constructor($state,
              $scope,
              $q,
              $uibModal,
              ENV,
              features,
              issuesService,
              ncUtilsFlash,
              usersService,
              issueUsersService,
              customersService,
              projectsService,
              resourcesService,
              coreUtils) {
    this.$state = $state;
    this.$scope = $scope;
    this.$q = $q;
    this.$uibModal = $uibModal;
    this.ENV = ENV;
    this.features = features;
    this.service = issuesService;
    this.issue = {};
    this.ncUtilsFlash = ncUtilsFlash;
    this.usersService = usersService;
    this.issueUsersService = issueUsersService;
    this.customersService = customersService;
    this.projectsService = projectsService;
    this.resourcesService = resourcesService;
    this.coreUtils = coreUtils;
    this.init();
  }

  init() {
    this.$scope.$watch(() => this.issue.caller, () => {
      this.issue.customer = null;
      this.refreshCustomers();
    });
    this.$scope.$watch(() => this.issue.customer, () => {
      this.issue.project = null;
      this.refreshProjects();
    });
    this.$scope.$watch(() => this.issue.project, () => {
      this.issue.resource = null;
      this.refreshResources();
    });
    this.$scope.$watch(() => this.issue.scope, () => {
      this.issue.resource = null;
      this.refreshResources();
    });
    this.scopes = this.getScopes();
    this.emptyFieldMessage = gettext('You did not enter a field.');
  }

  getScopes() {
    const filterResourceType = resourceType => this.features.isVisible(
      this.ENV.resourceCategory[resourceType]
    );

    const formatChoice = resourceType => ({
      display_name: resourceType.split('.').join(' '),
      value: resourceType
    });

    const types = Object.keys(this.ENV.resourceCategory);
    return types.filter(filterResourceType).sort().map(formatChoice);
  }

  refreshUsers(name) {
    const params = name && {full_name: name};
    return this.usersService.getList(params).then(users => {
      this.users = users;
    });
  }

  refreshSupportUsers(name) {
    const params = name && {name: name};
    return this.issueUsersService.getList(params).then(users => {
      this.supportUsers = users;
    });
  }

  refreshCustomers(name) {
    if (!this.issue.caller) {
      return;
    }
    let params = {
      user_uuid: this.issue.caller.uuid
    };
    if (name) {
      params.name = name;
    }
    return this.customersService.getList(params).then(customers => {
      this.customers = customers;
    });
  }

  refreshProjects(name) {
    if (!this.issue.customer) {
      return;
    }
    let params = {
      customer: this.issue.customer.uuid
    };
    if (name) {
      params.name = name;
    }
    this.projectsService.filterByCustomer = false;
    let promise = this.projectsService.getList(params).then(projects => {
      this.projects = projects;
    });
    this.projectsService.filterByCustomer = true;
    return promise;
  }

  refreshResources(name) {
    if (!this.issue.project || !this.issue.scope) {
      return;
    }

    let params = {
      project_uuid: this.issue.project.uuid,
      resource_type: this.issue.scope.value,
      field: ['name', 'url']
    };
    if (name) {
      params.name = name;
    }
    this.resourcesService.filterByCustomer = false;
    let promise = this.resourcesService.getList(params).then(resources => {
      this.resources = resources;
    });
    this.resourcesService.filterByCustomer = true;
    return promise;
  }

  filterByCaller(caller) {
    return this.onSearch({
      filter: {caller}
    });
  }

  filterByCustomer(customer) {
    return this.onSearch({
      filter: {customer}
    });
  }

  filterByProject(project) {
    return this.onSearch({
      filter: {project}
    });
  }

  save() {
    this.IssueForm.$submitted = true;
    if (this.IssueForm.$invalid) {
      return this.$q.reject();
    }
    let issue = {
      type: this.issue.type,
      customer: this.issue.customer.url,
      summary: this.issue.summary,
      description: this.issue.description,
      caller: this.issue.caller.url
    };
    if (this.issue.project) {
      project: this.issue.project.url;
    }
    if (this.issue.assignee) {
      issue.assignee = this.issue.assignee.url;
    }
    if (this.issue.resource) {
      issue.resource = this.issue.resource.url;
    }
    this.saving = true;
    return this.service.createIssue(issue).then(issue => {
      this.service.clearAllCacheForCurrentEndpoint();
      this.ncUtilsFlash.success(this.coreUtils.templateFormatter(gettext('Request {key} has been created.'), {key: issue.key}));
      return this.$state.go('support.detail', {uuid: issue.uuid});
    }).finally(() => {
      this.saving = false;
    });
  }

  openUserDialog(user) {
    this.$uibModal.open({
      component: 'userPopover',
      resolve: {
        user: () => user
      }
    });
  }

  openCustomerDialog(customer) {
    this.$uibModal.open({
      component: 'customerPopover',
      size: 'lg',
      resolve: {
        customer_uuid: () => customer.uuid,
      }
    });
  }
}
<commit_msg>Fix lint<commit_after>import template from './issue-registration.html';

export default function issueRegistration() {
  return {
    restrict: 'E',
    template: template,
    controller: IssueRegistrationController,
    controllerAs: '$ctrl',
    scope: {
      onSearch: '&'
    },
    bindToController: true
  };
}

// @ngInject
class IssueRegistrationController {
  constructor($state,
              $scope,
              $q,
              $uibModal,
              ENV,
              features,
              issuesService,
              ncUtilsFlash,
              usersService,
              issueUsersService,
              customersService,
              projectsService,
              resourcesService,
              coreUtils) {
    this.$state = $state;
    this.$scope = $scope;
    this.$q = $q;
    this.$uibModal = $uibModal;
    this.ENV = ENV;
    this.features = features;
    this.service = issuesService;
    this.issue = {};
    this.ncUtilsFlash = ncUtilsFlash;
    this.usersService = usersService;
    this.issueUsersService = issueUsersService;
    this.customersService = customersService;
    this.projectsService = projectsService;
    this.resourcesService = resourcesService;
    this.coreUtils = coreUtils;
    this.init();
  }

  init() {
    this.$scope.$watch(() => this.issue.caller, () => {
      this.issue.customer = null;
      this.refreshCustomers();
    });
    this.$scope.$watch(() => this.issue.customer, () => {
      this.issue.project = null;
      this.refreshProjects();
    });
    this.$scope.$watch(() => this.issue.project, () => {
      this.issue.resource = null;
      this.refreshResources();
    });
    this.$scope.$watch(() => this.issue.scope, () => {
      this.issue.resource = null;
      this.refreshResources();
    });
    this.scopes = this.getScopes();
    this.emptyFieldMessage = gettext('You did not enter a field.');
  }

  getScopes() {
    const filterResourceType = resourceType => this.features.isVisible(
      this.ENV.resourceCategory[resourceType]
    );

    const formatChoice = resourceType => ({
      display_name: resourceType.split('.').join(' '),
      value: resourceType
    });

    const types = Object.keys(this.ENV.resourceCategory);
    return types.filter(filterResourceType).sort().map(formatChoice);
  }

  refreshUsers(name) {
    const params = name && {full_name: name};
    return this.usersService.getList(params).then(users => {
      this.users = users;
    });
  }

  refreshSupportUsers(name) {
    const params = name && {name: name};
    return this.issueUsersService.getList(params).then(users => {
      this.supportUsers = users;
    });
  }

  refreshCustomers(name) {
    if (!this.issue.caller) {
      return;
    }
    let params = {
      user_uuid: this.issue.caller.uuid
    };
    if (name) {
      params.name = name;
    }
    return this.customersService.getList(params).then(customers => {
      this.customers = customers;
    });
  }

  refreshProjects(name) {
    if (!this.issue.customer) {
      return;
    }
    let params = {
      customer: this.issue.customer.uuid
    };
    if (name) {
      params.name = name;
    }
    this.projectsService.filterByCustomer = false;
    let promise = this.projectsService.getList(params).then(projects => {
      this.projects = projects;
    });
    this.projectsService.filterByCustomer = true;
    return promise;
  }

  refreshResources(name) {
    if (!this.issue.project || !this.issue.scope) {
      return;
    }

    let params = {
      project_uuid: this.issue.project.uuid,
      resource_type: this.issue.scope.value,
      field: ['name', 'url']
    };
    if (name) {
      params.name = name;
    }
    this.resourcesService.filterByCustomer = false;
    let promise = this.resourcesService.getList(params).then(resources => {
      this.resources = resources;
    });
    this.resourcesService.filterByCustomer = true;
    return promise;
  }

  filterByCaller(caller) {
    return this.onSearch({
      filter: {caller}
    });
  }

  filterByCustomer(customer) {
    return this.onSearch({
      filter: {customer}
    });
  }

  filterByProject(project) {
    return this.onSearch({
      filter: {project}
    });
  }

  save() {
    this.IssueForm.$submitted = true;
    if (this.IssueForm.$invalid) {
      return this.$q.reject();
    }
    let issue = {
      type: this.issue.type,
      customer: this.issue.customer.url,
      summary: this.issue.summary,
      description: this.issue.description,
      caller: this.issue.caller.url
    };
    if (this.issue.project) {
      issue.project: this.issue.project.url;
    }
    if (this.issue.assignee) {
      issue.assignee = this.issue.assignee.url;
    }
    if (this.issue.resource) {
      issue.resource = this.issue.resource.url;
    }
    this.saving = true;
    return this.service.createIssue(issue).then(issue => {
      this.service.clearAllCacheForCurrentEndpoint();
      this.ncUtilsFlash.success(this.coreUtils.templateFormatter(gettext('Request {key} has been created.'), {key: issue.key}));
      return this.$state.go('support.detail', {uuid: issue.uuid});
    }).finally(() => {
      this.saving = false;
    });
  }

  openUserDialog(user) {
    this.$uibModal.open({
      component: 'userPopover',
      resolve: {
        user: () => user
      }
    });
  }

  openCustomerDialog(customer) {
    this.$uibModal.open({
      component: 'customerPopover',
      size: 'lg',
      resolve: {
        customer_uuid: () => customer.uuid,
      }
    });
  }
}
<|endoftext|>


<commit_before>window.onload = function(){
  theGame.run();
}

var theGame = {
  EMPTY: 0,
  ROCK: -1,
  board: null,
  theme: 'metro',
  themes: {
    'metro': {
      'rock': 'metro',
      'regularPieces': ['m1', 'm2', 'm3', 'm3bis', 'm4', 'm5', 'm6', 'm7', 'm7bis', 'm8', 'm9', 'm10', 'm11', 'm12', 'm13', 'm14']
    }
  },
  currentPieces: [],
  validPieces: [],
  currentPiece: 0,
  currentPosX: 9,
  currentPosY: 7,
  maxAvailablePieces: 0,
  nbPieces: 0,
  level: 0,
  score: 0,

  init: function init() {
    theGame.board = Raphael(document.body, 320, 480);

    var border = theGame.board.rect(0.5, 0.5, 319, 479),
        header = theGame.board.path('M 0 0 l 0 225 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 120 0 l 0 -50 z'),
        title = theGame.board.print(0, 40, "esviji", theGame.board.getFont('ChewyRegular'), 60),
        copyright = theGame.board.print(10, 70, "(c) Nicolas Hoizey", theGame.board.getFont('ChewyRegular'), 9),
        score = theGame.board.print(220, 25, "score: 0", theGame.board.getFont('ChewyRegular'), 25);

    header.attr({
      'fill': '#9999cc',
      'stroke': '#666699',
      'stroke-width': 1
    });

    theGame.maxAvailablePieces = theGame.themes[theGame.theme].regularPieces.length;
  },

  play: function play() {
    theGame.nextLevel();
    theGame.playUserChoice();
    /*
    while (theGame.validPieces.length > 0) {
      theGame.waitForUser();
      theGame.playUserChoice();
    }
    theGame.play();
    */
  },

  nextLevel: function nextLevel() {
    theGame.level++;
    theGame.nbPieces = Math.min(theGame.maxAvailablePieces, Math.floor(5 + (theGame.level / 5)));

    theGame.initPieces();
    theGame.drawPieces();

    theGame.getValidPieces();
    theGame.currentPiece = theGame.validPieces[Math.floor(Math.random() * theGame.validPieces.length)];
    pieceFile = 'themes/' + theGame.theme + '/' + theGame.themes[theGame.theme].regularPieces[theGame.currentPiece - 1] + '.svg';
    piece_x = theGame.currentPosX * 35 - 30;
    piece_y = 480 - 35 * theGame.currentPosY;
    theGame.drawnCurrentPiece = theGame.board.image(pieceFile, piece_x, piece_y, 30, 30);
  },

  playUserChoice: function playUserChoice () {
    var stopped = false;

    theGame.currentDirX = -1;
    theGame.currentDirY = 0;

    while (!stopped) {
      if (theGame.currentPosY == 1 && theGame.currentDirY == -1) {
        stopped = true;
      } else {
        if (theGame.currentPosX == 1 && theGame.currentDirX == -1) {
          theGame.currentDirX = 0;
          theGame.currentDirY = -1;
        } else {
          nextPiece = theGame.currentPieces[theGame.currentPosX + theGame.currentDirX][theGame.currentPosY + theGame.currentDirY];
          if (nextPiece == theGame.ROCK) {
            if (theGame.currentDirX == -1) {
              theGame.currentDirX = 0;
              theGame.currentDirY = -1;
            } else {
              stopped = true;
            }
          } else {
            if (nextPiece == theGame.EMPTY) {
              theGame.moveOnce();
            } else {
              if (nextPiece == theGame.currentPiece) {
                theGame.moveOnce();
              } else {
                theGame.currentPiece = nextPiece;
                stopped = true;
              }
            }
          }
        }
      }
    }
  },

  moveOnce: function moveOnce() {
    theGame.currentPosX += theGame.currentDirX;
    theGame.currentPosY += theGame.currentDirY;
    piece_x = theGame.currentPosX * 35 - 30;
    piece_y = 480 - 35 * theGame.currentPosY;
    anim = Raphael.animation({'x': piece_x, 'y': piece_y}, 1000, 'linear');
    theGame.drawnCurrentPiece.animate(anim.delay(1000));
  },

  initPieces: function initPieces() {
    theGame.currentPieces = [];

    for(x = 1; x <= 8; x++) {
      theGame.currentPieces[x] = [];
      for (y = 1; y <= 12; y++) {
        if (x > 6) {
          theGame.currentPieces[x][y] = theGame.EMPTY;
        } else {
          if (y > 6) {
            if (y - 6 > x) {
              theGame.currentPieces[x][y] = theGame.ROCK;
            } else {
              theGame.currentPieces[x][y] = theGame.EMPTY;
            }
          } else {
            theGame.currentPieces[x][y] = 1 + Math.floor(Math.random() * theGame.nbPieces);
          }
        }
      }
    }

    // add rocks in the middle after level 10
    if (theGame.level > 10) {
      nbRocks = Math.floor((theGame.level - 5) / 5);
      positionedRocks = 0;
      while (positionedRocks < nbRocks) {
        rock_x = 1 + Math.floor(Math.random() * 6);
        rock_y = 1 + Math.floor(Math.random() * 6);
        if (theGame.currentPieces[rock_x][rock_y] != theGame.ROCK) {
          theGame.currentPieces[rock_x][rock_y] = theGame.ROCK;
          positionedRocks++;
        }
      }
    }
  },

  drawPieces: function drawPieces() {
    for(x = 1; x <= 6; x++) {
      for (y = 1; y <= 6; y++) {
        if (theGame.currentPieces[x][y] != theGame.EMPTY) {
          if (theGame.currentPieces[x][y] == theGame.ROCK) {
            pieceFile = 'themes/' + theGame.theme + '/' + theGame.themes[theGame.theme].rock + '.svg';
          } else {
            pieceFile = 'themes/' + theGame.theme + '/' + theGame.themes[theGame.theme].regularPieces[theGame.currentPieces[x][y] - 1] + '.svg';
          }
          piece_x = x * 35 - 30;
          piece_y = 480 - 35 * y;
          drawnPiece = theGame.board.image(pieceFile, piece_x, -30, 30, 30);
          drawnPiece.animate({'y': piece_y}, 2000, 'bounce');
        }
      }
    }
  },

  getValidPieces: function getValidPieces() {
    var x, y, dir_x, dir_y, found;

    theGame.validPieces = [];

    for (y_start = 1; y_start <= 12; y_start++) {
      x = 9;
      y = y_start;
      dir_x = -1;
      dir_y = 0;
      found = false;
      while (!found) {
        if (y == 1 && dir_y == -1) {
          found = true;
        } else {
          if (x == 1 && dir_x == -1) {
            dir_x = 0;
            dir_y = -1;
          } else {
            nextPiece = theGame.currentPieces[x + dir_x][y + dir_y];
            if (nextPiece == theGame.ROCK) {
              if (dir_x == -1) {
                dir_x = 0;
                dir_y = -1;
              } else {
                found = true;
              }
            } else {
              if (nextPiece == theGame.EMPTY) {
                x += dir_x;
                y += dir_y;
              } else {
                if (theGame.validPieces.indexOf(nextPiece) == -1) {
                  theGame.validPieces.push(nextPiece);
                }
                found = true;
              }
            }
          }
        }
      }
    }
  },

  run: function run() {
    theGame.init();
    theGame.play();
  }
}<commit_msg>Its name is esviji!<commit_after>window.onload = function(){
  esviji.run();
}

var esviji = {
  EMPTY: 0,
  ROCK: -1,
  board: null,
  theme: 'metro',
  themes: {
    'metro': {
      'rock': 'metro',
      'regularPieces': ['m1', 'm2', 'm3', 'm3bis', 'm4', 'm5', 'm6', 'm7', 'm7bis', 'm8', 'm9', 'm10', 'm11', 'm12', 'm13', 'm14']
    }
  },
  currentPieces: [],
  validPieces: [],
  currentPiece: 0,
  currentPosX: 9,
  currentPosY: 7,
  maxAvailablePieces: 0,
  nbPieces: 0,
  level: 0,
  score: 0,

  init: function init() {
    esviji.board = Raphael(document.body, 320, 480);

    var border = esviji.board.rect(0.5, 0.5, 319, 479),
        header = esviji.board.path('M 0 0 l 0 225 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 0 -35 l 35 0 l 120 0 l 0 -50 z'),
        title = esviji.board.print(0, 40, "esviji", esviji.board.getFont('ChewyRegular'), 60),
        copyright = esviji.board.print(10, 70, "(c) Nicolas Hoizey", esviji.board.getFont('ChewyRegular'), 9),
        score = esviji.board.print(220, 25, "score: 0", esviji.board.getFont('ChewyRegular'), 25);

    header.attr({
      'fill': '#9999cc',
      'stroke': '#666699',
      'stroke-width': 1
    });

    esviji.maxAvailablePieces = esviji.themes[esviji.theme].regularPieces.length;
  },

  play: function play() {
    esviji.nextLevel();
    esviji.getNewPiece();
    esviji.playUserChoice();
    /*
    while (esviji.validPieces.length > 0) {
      esviji.waitForUser();
      esviji.playUserChoice();
    }
    esviji.play();
    */
  },

  nextLevel: function nextLevel() {
    esviji.level++;
    esviji.nbPieces = Math.min(esviji.maxAvailablePieces, Math.floor(5 + (esviji.level / 5)));

    esviji.initPieces();
    esviji.drawPieces();
  },

  getNewPiece: function getNewPiece() {
    esviji.currentPosX = 9;
    esviji.currentPosY = 8;
    esviji.getValidPieces();
    esviji.currentPiece = esviji.validPieces[Math.floor(Math.random() * esviji.validPieces.length)];
    pieceFile = 'themes/' + esviji.theme + '/' + esviji.themes[esviji.theme].regularPieces[esviji.currentPiece - 1] + '.svg';
    piece_x = esviji.currentPosX * 35 - 30;
    piece_y = 480 - 35 * esviji.currentPosY;
    esviji.drawnCurrentPiece = esviji.board.image(pieceFile, piece_x, piece_y, 30, 30);
  },

  playUserChoice: function playUserChoice () {
    var stopped = false;

    esviji.currentDirX = -1;
    esviji.currentDirY = 0;

    while (!stopped) {
      if (esviji.currentPosY == 1 && esviji.currentDirY == -1) {
        stopped = true;
      } else {
        if (esviji.currentPosX == 1 && esviji.currentDirX == -1) {
          esviji.currentDirX = 0;
          esviji.currentDirY = -1;
        } else {
          nextPiece = esviji.currentPieces[esviji.currentPosX + esviji.currentDirX][esviji.currentPosY + esviji.currentDirY];
          if (nextPiece == esviji.ROCK) {
            if (esviji.currentDirX == -1) {
              esviji.currentDirX = 0;
              esviji.currentDirY = -1;
            } else {
              stopped = true;
            }
          } else {
            if (nextPiece == esviji.EMPTY) {
              esviji.moveOnce();
            } else {
              if (nextPiece == esviji.currentPiece) {
                esviji.moveOnce();
              } else {
                esviji.currentPiece = nextPiece;
                stopped = true;
              }
            }
          }
        }
      }
    }
  },

  moveOnce: function moveOnce() {
    esviji.currentPosX += esviji.currentDirX;
    esviji.currentPosY += esviji.currentDirY;
    piece_x = esviji.currentPosX * 35 - 30;
    piece_y = 480 - 35 * esviji.currentPosY;
    anim = Raphael.animation({'x': piece_x, 'y': piece_y}, 1000, 'linear');
    esviji.drawnCurrentPiece.animate(anim.delay(1000));
  },

  initPieces: function initPieces() {
    esviji.currentPieces = [];

    for(x = 1; x <= 8; x++) {
      esviji.currentPieces[x] = [];
      for (y = 1; y <= 12; y++) {
        if (x > 6) {
          esviji.currentPieces[x][y] = esviji.EMPTY;
        } else {
          if (y > 6) {
            if (y - 6 > x) {
              esviji.currentPieces[x][y] = esviji.ROCK;
            } else {
              esviji.currentPieces[x][y] = esviji.EMPTY;
            }
          } else {
            esviji.currentPieces[x][y] = 1 + Math.floor(Math.random() * esviji.nbPieces);
          }
        }
      }
    }

    // add rocks in the middle after level 10
    if (esviji.level > 10) {
      nbRocks = Math.floor((esviji.level - 5) / 5);
      positionedRocks = 0;
      while (positionedRocks < nbRocks) {
        rock_x = 1 + Math.floor(Math.random() * 6);
        rock_y = 1 + Math.floor(Math.random() * 6);
        if (esviji.currentPieces[rock_x][rock_y] != esviji.ROCK) {
          esviji.currentPieces[rock_x][rock_y] = esviji.ROCK;
          positionedRocks++;
        }
      }
    }
  },

  drawPieces: function drawPieces() {
    for(x = 1; x <= 6; x++) {
      for (y = 1; y <= 6; y++) {
        if (esviji.currentPieces[x][y] != esviji.EMPTY) {
          if (esviji.currentPieces[x][y] == esviji.ROCK) {
            pieceFile = 'themes/' + esviji.theme + '/' + esviji.themes[esviji.theme].rock + '.svg';
          } else {
            pieceFile = 'themes/' + esviji.theme + '/' + esviji.themes[esviji.theme].regularPieces[esviji.currentPieces[x][y] - 1] + '.svg';
          }
          piece_x = x * 35 - 30;
          piece_y = 480 - 35 * y;
          drawnPiece = esviji.board.image(pieceFile, piece_x, -30, 30, 30);
          drawnPiece.animate({'y': piece_y}, 2000, 'bounce');
        }
      }
    }
  },

  getValidPieces: function getValidPieces() {
    var x, y, dir_x, dir_y, found;

    esviji.validPieces = [];

    for (y_start = 1; y_start <= 12; y_start++) {
      x = 9;
      y = y_start;
      dir_x = -1;
      dir_y = 0;
      found = false;
      while (!found) {
        if (y == 1 && dir_y == -1) {
          found = true;
        } else {
          if (x == 1 && dir_x == -1) {
            dir_x = 0;
            dir_y = -1;
          } else {
            nextPiece = esviji.currentPieces[x + dir_x][y + dir_y];
            if (nextPiece == esviji.ROCK) {
              if (dir_x == -1) {
                dir_x = 0;
                dir_y = -1;
              } else {
                found = true;
              }
            } else {
              if (nextPiece == esviji.EMPTY) {
                x += dir_x;
                y += dir_y;
              } else {
                if (esviji.validPieces.indexOf(nextPiece) == -1) {
                  esviji.validPieces.push(nextPiece);
                }
                found = true;
              }
            }
          }
        }
      }
    }
  },

  run: function run() {
    esviji.init();
    esviji.play();
  }
}<|endoftext|>


<commit_before>/**
 * Used to view the details of an earnings entry.
 *
 * @module kocomponents/earnings/viewer
 *
 */
import Komponent from '../../helpers/KnockoutComponent';
import clients from '../../../data/clients';
import getObservable from '../../../utils/getObservable';
import ko from 'knockout';
import { show as showError } from '../../../modals/error';
import template from './template.html';
import { item as userEarningsItem } from '../../../data/userEarnings';

const TAG_NAME = 'earnings-viewer';

/**
 * Component
 */
export default class EarningsViewer extends Komponent {

    static get template() { return template; }

    /**
     * @param {object} params
     * @param {(number|KnockoutObservable<number>)}
     * [params.earningsEntryID]
     */
    constructor(params) {
        super();

        /**
         * Holds the ID for the earnings entry being viewed.
         * @member {KnockoutObservable<number>}
         */
        this.earningsEntryID = getObservable(params.earningsEntryID || null);

        /**
         * Earnings entry returned for a given ID.
         * @member {KnockoutObservable<object>}
         */
        this.earningsEntry = ko.observable();

        /**
         * Gets a (aria) label for the edit link
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.getEditLinkLabel = (item) => `Edit earnings entry ${item.earningsEntryID}`;

        /**
         * Build a link to edit the item
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.linkToEdit = (item) => `/earnings-edit/${item.earningsEntryID}?mustReturn=earnings-view/${item.earningsEntryID}&returnText=View Earnings`;

        /**
         * Display the duration of an entry
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.displayDuration = (item) => {
            const hours = Math.floor(item.durationMinutes / 60);
            const minutes = item.durationMinutes - (hours * 60);
            return `${hours} hours ${minutes} minutes`;
        };

        /**
         * Holds an object with the client information
         * @member {KnockoutObservable<models/Client>}
         */
        this.client = ko.observable(null);

        /**
         * Display the client name/info of the current earning entry
         * @member {KnockoutComputed<string>}
         */
        this.displayClient = ko.pureComputed(() => {
            const c = this.client();
            if (c) {
                return c.fullName();
            }
            else {
                return '';
            }
        });

        /**
         * Holds a subscription to updates about data for a specific item
         * @private {SingleEvent/Subscription}
         */
        let dataSubscription;
        /**
         * Holds a subscription to error notifications load data for a specific item
         * @private {SingleEvent/Subscription}
         */
        let dataErrorSubscription;
        /**
         * Reset current data displayed and remove previous subscriptions
         * to data updates.
         * Useful when the ID changes, in order to prevent displaying previous ID
         * data and stop receiving notifications for that.
         * @private
         * @method
         */
        const resetData = () => {
            this.earningsEntry(null);
            this.client(null);
            if (dataSubscription) {
                dataSubscription.dispose();
            }
            if (dataErrorSubscription) {
                dataErrorSubscription.dispose();
            }
        };

        /**
         * When the ID changes, the information is
         * updated for the specific platform.
         */
        this.observeChanges(() => {
            const id = this.earningsEntryID();
            // reset data and previous ID notifications
            resetData();
            if (id) {
                const item = userEarningsItem(id);
                // Load item data
                dataSubscription = this.subscribeTo(item.onData, (data) => {
                    this.earningsEntry(data);
                    // Load info about the client of this entry
                    // It's optional, so careful since can be null
                    if (data.clientUserID) {
                        clients.item(data.clientUserID)
                        .onceLoaded()
                        .then((client) => {
                            this.client(client);
                        })
                        .catch((error) => {
                            showError({
                                title: 'There was an error loading the client information at the entry',
                                error
                            });
                        });
                    }
                });
                // Notify data load errors
                dataErrorSubscription = this.subscribeTo(item.onDataError, (error) => {
                    showError({
                        title: 'There was an error loading the earning entry',
                        error
                    });
                });
            }
        });
    }
}

ko.components.register(TAG_NAME, EarningsViewer);

<commit_msg>Fixed clients data module import at earnings viewer #776<commit_after>/**
 * Used to view the details of an earnings entry.
 *
 * @module kocomponents/earnings/viewer
 *
 */
import Client from '../../../models/Client';
import Komponent from '../../helpers/KnockoutComponent';
import { item as clientsDataItem } from '../../../data/clients';
import getObservable from '../../../utils/getObservable';
import ko from 'knockout';
import { show as showError } from '../../../modals/error';
import template from './template.html';
import { item as userEarningsItem } from '../../../data/userEarnings';

const TAG_NAME = 'earnings-viewer';

/**
 * Component
 */
export default class EarningsViewer extends Komponent {

    static get template() { return template; }

    /**
     * @param {object} params
     * @param {(number|KnockoutObservable<number>)}
     * [params.earningsEntryID]
     */
    constructor(params) {
        super();

        /**
         * Holds the ID for the earnings entry being viewed.
         * @member {KnockoutObservable<number>}
         */
        this.earningsEntryID = getObservable(params.earningsEntryID || null);

        /**
         * Earnings entry returned for a given ID.
         * @member {KnockoutObservable<object>}
         */
        this.earningsEntry = ko.observable();

        /**
         * Gets a (aria) label for the edit link
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.getEditLinkLabel = (item) => `Edit earnings entry ${item.earningsEntryID}`;

        /**
         * Build a link to edit the item
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.linkToEdit = (item) => `/earnings-edit/${item.earningsEntryID}?mustReturn=earnings-view/${item.earningsEntryID}&returnText=View Earnings`;

        /**
         * Display the duration of an entry
         * @param {object} item Earnings entry plain object
         * @returns {string}
         */
        this.displayDuration = (item) => {
            const hours = Math.floor(item.durationMinutes / 60);
            const minutes = item.durationMinutes - (hours * 60);
            return `${hours} hours ${minutes} minutes`;
        };

        /**
         * Holds an object with the client information
         * @member {KnockoutObservable<models/Client>}
         */
        this.client = ko.observable(null);

        /**
         * Display the client name/info of the current earning entry
         * @member {KnockoutComputed<string>}
         */
        this.displayClient = ko.pureComputed(() => {
            const c = new Client(this.client());
            if (c) {
                return c.fullName();
            }
            else {
                return '';
            }
        });

        /**
         * Holds a subscription to updates about data for a specific item
         * @private {SingleEvent/Subscription}
         */
        let dataSubscription;
        /**
         * Holds a subscription to error notifications load data for a specific item
         * @private {SingleEvent/Subscription}
         */
        let dataErrorSubscription;
        /**
         * Reset current data displayed and remove previous subscriptions
         * to data updates.
         * Useful when the ID changes, in order to prevent displaying previous ID
         * data and stop receiving notifications for that.
         * @private
         * @method
         */
        const resetData = () => {
            this.earningsEntry(null);
            this.client(null);
            if (dataSubscription) {
                dataSubscription.dispose();
            }
            if (dataErrorSubscription) {
                dataErrorSubscription.dispose();
            }
        };

        /**
         * When the ID changes, the information is
         * updated for the specific platform.
         */
        this.observeChanges(() => {
            const id = this.earningsEntryID();
            // reset data and previous ID notifications
            resetData();
            if (id) {
                const item = userEarningsItem(id);
                // Load item data
                dataSubscription = this.subscribeTo(item.onData, (data) => {
                    this.earningsEntry(data);
                    // Load info about the client of this entry
                    // It's optional, so careful since can be null
                    if (data.clientUserID) {
                        clientsDataItem(data.clientUserID)
                        .onceLoaded()
                        .then((client) => {
                            this.client(client);
                        })
                        .catch((error) => {
                            showError({
                                title: 'There was an error loading the client information at the entry',
                                error
                            });
                        });
                    }
                });
                // Notify data load errors
                dataErrorSubscription = this.subscribeTo(item.onDataError, (error) => {
                    showError({
                        title: 'There was an error loading the earning entry',
                        error
                    });
                });
            }
        });
    }
}

ko.components.register(TAG_NAME, EarningsViewer);

<|endoftext|>


<commit_before>/**
 * @fileOverview The frontpage app
 */
// require jQuery: not needed, loads from script tag from cnd
// require('../static/components/jquery/dist/jquery.js');

var frontapp = module.exports = {};

/**
 * Boot frontapp
 */
frontapp.init = function() {

  console.log($('#input'));
  console.log($('#input').val());
  var dataString = $('#input').val();

  $('#submit').click(function(event) {
    $.ajax({
      type: "POST",
      url: '/parse',
      data: dataString,
      success: function() {
        console.log('Success?');
      },
      dataType: 'text'
    });
  });
};

if (window.location.href.match(/\//)) {
  frontapp.init();
}
<commit_msg>fix frontapp js script to POST correct<commit_after>/**
 * @fileOverview The frontpage app
 */

// require jQuery: not needed, loads from script tag from cnd
// require('../static/components/jquery/dist/jquery.js');

var frontapp = module.exports = {};

/**
 * Boot frontapp
 */
frontapp.init = function() {

  var dataString = $('#input').val().replace(/\n/g, '|');
  console.log('This stuff will be POSTed:', dataString);

  $('#submit').click(function(event) {
    $.ajax({
      type: "POST",
      url: '/parse',
      data: {
        dataString: dataString
      },
      success: function() {
        console.log('Success');
      },
      dataType: 'json'
    });
  });
};

if (window.location.href.match(/\//)) {
  frontapp.init();
}
<|endoftext|>


<commit_before>function NonCancellableEvent() {
  this._monitors = [], this._observers = [];
}

NonCancellableEvent.prototype.addMonitor = function(handler, filter) {
  this._monitors.push({ shouldHandle: filter, notify: handler });
};

NonCancellableEvent.prototype.addObserver = function(handler, filter) {
  this._observers.push({ shouldHandle: filter, notify: handler });
};

NonCancellableEvent.prototype.fire = function(data) {
  this._monitors.forEach(function(monitor) {
    if (monitor.shouldHandle(data)) {
      monitor.notify(data);
    }
  });
  this._observers.forEach(function(observer) {
    if (observer.shouldHandle(data)) {
      observer.notify(data);
    }
  });
};

function CancellableEvent() {
  NonCancellableEvent.call(this);
  this._modifiers = [];
}

CancellableEvent.prototype = NonCancellableEvent.prototype;
CancellableEvent.prototype.constructor = CancellableEvent;

CancellableEvent.prototype.addModifier = function(handler, filter) {
  this._modifiers.push({ shouldHandle: filter, modify: handler });
};

CancellableEvent.prototype.fire = function(data) {
  this._monitors.forEach(function(monitor) {
    if (monitor.shouldHandle(data)) {
      monitor.notify(data);
    }
  });
  this._modifiers.forEach(function(modifier) {
    if (modifier.shouldHandle(data)) {
      data = modifier.modify(data);
    }
  });
  if (!data.consumed) {
    this._observers.forEach(function(observer) {
      if (observer.shouldHandle(data)) {
        observer.notify(data);
      }
    });
  }
};

var eventTypes = {
  chat:    new CancellableEvent(),
  command: new CancellableEvent(),
  join:    new CancellableEvent(),
  quit:    new NonCancellableEvent()
};

function noOpFilter() {
  return true;
}

function before(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addMonitor) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addMonitor(handler, filter);
  } else {
    // TODO
  }
}

function on(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addModifier) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addModifier(handler, filter);
  } else {
    // TODO
  }
}

function after(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addObserver) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addObserver(handler, filter);
  } else {
    // TODO
  }
}

function fire(eventType, data) {
  eventTypes[eventType].fire(data);
}

module.exports = {
  NonCancellableEvent: NonCancellableEvent,
  CancellableEvent: CancellableEvent,
  before: before,
  on: on,
  after: after,
  fire: fire
};
<commit_msg>Don't export event class definitions from events module<commit_after>function NonCancellableEvent() {
  this._monitors = [], this._observers = [];
}

NonCancellableEvent.prototype.addMonitor = function(handler, filter) {
  this._monitors.push({ shouldHandle: filter, notify: handler });
};

NonCancellableEvent.prototype.addObserver = function(handler, filter) {
  this._observers.push({ shouldHandle: filter, notify: handler });
};

NonCancellableEvent.prototype.fire = function(data) {
  this._monitors.forEach(function(monitor) {
    if (monitor.shouldHandle(data)) {
      monitor.notify(data);
    }
  });
  this._observers.forEach(function(observer) {
    if (observer.shouldHandle(data)) {
      observer.notify(data);
    }
  });
};

function CancellableEvent() {
  NonCancellableEvent.call(this);
  this._modifiers = [];
}

CancellableEvent.prototype = NonCancellableEvent.prototype;
CancellableEvent.prototype.constructor = CancellableEvent;

CancellableEvent.prototype.addModifier = function(handler, filter) {
  this._modifiers.push({ shouldHandle: filter, modify: handler });
};

CancellableEvent.prototype.fire = function(data) {
  this._monitors.forEach(function(monitor) {
    if (monitor.shouldHandle(data)) {
      monitor.notify(data);
    }
  });
  this._modifiers.forEach(function(modifier) {
    if (modifier.shouldHandle(data)) {
      data = modifier.modify(data);
    }
  });
  if (!data.consumed) {
    this._observers.forEach(function(observer) {
      if (observer.shouldHandle(data)) {
        observer.notify(data);
      }
    });
  }
};

var eventTypes = {
  chat:    new CancellableEvent(),
  command: new CancellableEvent(),
  join:    new CancellableEvent(),
  quit:    new NonCancellableEvent()
};

function noOpFilter() {
  return true;
}

function before(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addMonitor) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addMonitor(handler, filter);
  } else {
    // TODO
  }
}

function on(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addModifier) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addModifier(handler, filter);
  } else {
    // TODO
  }
}

function after(eventType, filter, handler) {
  var event = eventTypes[eventType];
  if (event.addObserver) {
    if (typeof handler == 'undefined') {
      handler = filter;
      filter = noOpFilter;
    }
    event.addObserver(handler, filter);
  } else {
    // TODO
  }
}

function fire(eventType, data) {
  eventTypes[eventType].fire(data);
}

module.exports = {
  before: before,
  on: on,
  after: after,
  fire: fire
};
<|endoftext|>