<commit_before>import GeoJSON from 'geojson';
import { Record } from '../../models/record.model';
import Specie from '../../models/specie.model';

/**
 * @swagger
 * /species/records/{taxID}:
 *   get:
 *     description: "All the records of an acceptedNameUsage (using internal taxID as key): query (use = true & visualizationPrivileges = 0)"
 *     operationId: REC1
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function read(req, res) {
  if (req.params.taxID) {
    try {
      const docs = await Record.aggregate([
        {
          $match: {
            taxID: +req.params.taxID,
            use: true,
            visualizationPrivileges: 0,
            spatialDuplicated: false
          }
        },
        {
          $project: {
            reported: {
              $cond: {
                if: {
                  $and: [{ $isArray: '$reported' }, { $ne: ['$reported', []] }]
                },
                then: { $isArray: '$reported' },
                else: false
              }
            },
            updated: {
              $cond: {
                if: {
                  $and: [{ $isArray: '$updated' }, { $ne: ['$updated', []] }]
                },
                then: { $isArray: '$updated' },
                else: false
              }
            },
            _id: 1,
            taxID: 1,
            acceptedNameUsage: 1,
            species: 1,
            speciesOriginal: 1,
            locality: 1,
            lat: 1,
            lon: 1,
            alt: 1,
            basisOfRecord: 1,
            catalogNumber: 1,
            collector: 1,
            institution: 1,
            url: 1,
            dd: 1,
            mm: 1,
            yyyy: 1,
            suggestedStateProvince: 1,
            suggestedCounty: 1,
            environmentalOutlier: 1,
            source: 1
          }
        }
      ]);
      res.send(GeoJSON.parse(docs, { Point: ['lat', 'lon'] }));
    } catch (err) {
      res.send(err);
    }
  }
}

/**
 * @swagger
 * /species:
 *   get:
 *     description: "Get all the species in BioModelos"
 *     operationId: SPE1
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function getAllSpecies(req, res) {
  try {
    const docs = await Specie.find({}, { species: 1, taxID: 1, _id: 0 });
    res.json(docs);
  } catch (err) {
    res.json(err);
  }
}

/**
 * @swagger
 * /species/{taxID}:
 *   get:
 *     description: "Get superior taxonomy and the total of records of a species"
 *     operationId: SPE2
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function getTaxonomyAndRecords(req, res) {
  if (req.params.taxID) {
    try {
      const doc = await Specie.find(
        { taxID: +req.params.taxID },
        {
          _id: 0,
          acceptedNameUsage: 1,
          species: 1,
          kingdom: 1,
          phylum: 1,
          class: 1,
          order: 1,
          family: 1
        }
      );
      try {
        const doc2 = await Record.aggregate([
          {
            $match: {
              taxID: +req.params.taxID,
              use: true,
              spatialDuplicated: false
            }
          },
          {
            $group: {
              _id: {
                characteristics: { taxID: '$taxID' }
              },
              totalRecords: { $sum: 1 }
            }
          },
          {
            $project: {
              _id: 0,
              taxID: '$_id.characteristics.taxID',
              totalRecords: '$totalRecords'
            }
          }
        ]);
        if (doc2[0] && doc2[0].totalRecords) {
          doc[0]['_doc']['totalRecords'] = doc2[0].totalRecords;
        } else {
          doc[0]['_doc']['totalRecords'] = 0;
        }
        res.json(doc);
      } catch (err) {
        res.json(err);
      }
    } catch (err) {
      res.json(err);
    }
  }
}

/**
 * @swagger
 * /species/search/{species}:
 *   get:
 *     description: "Get general query to obtain species with some specific characteristics"
 *     operationId: SPE3
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function searchSpecie(req, res) {
  if (
    req.params.species &&
    (!req.query.bmClass1 &&
      !req.query.bmClass2 &&
      !req.query.bmClass3 &&
      !req.query.bmClass4 &&
      !req.query.bmClass5 &&
      !req.query.bmClass6 &&
      !req.query.bmClass7)
  ) {
    const regEx = new RegExp(req.params.species, 'ig');
    if (!req.query.endangered && !req.query.endemic && !req.query.invasive) {
      try {
        const docs = await Specie.find(
          { species: { $regex: regEx } },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      (!req.query.endemic && !req.query.invasive)
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { species: { $regex: regEx } },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      req.query.endemic == 1 &&
      !req.query.invasive
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ endemic: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      req.query.endemic == 1 &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ endemic: { $in: [true] } }] },
              { $or: [{ invasive: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      req.query.endemic == 1 &&
      !req.query.invasive
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ endemic: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      req.query.endemic == 1 &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ endemic: { $in: [true] } }] },
              { $or: [{ invasive: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      !req.query.endemic &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ invasive: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered &&
      !req.query.endemic &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ invasive: { $in: [true] } }] }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    }
  } else if (
    req.params.species &&
    (req.query.bmClass1 ||
      req.query.bmClass2 ||
      req.query.bmClass3 ||
      req.query.bmClass4 ||
      req.query.bmClass5 ||
      req.query.bmClass6 ||
      req.query.bmClass7)
  ) {
    const regEx = new RegExp(req.params.species, 'ig');
    if (!req.query.endangered && !req.query.endemic && !req.query.invasive) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { species: { $regex: regEx } },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      (!req.query.endemic && !req.query.invasive)
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { species: { $regex: regEx } },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      req.query.endemic == 1 &&
      !req.query.invasive
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ endemic: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered == 1 &&
      req.query.endemic == 1 &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ endemic: { $in: [true] } }] },
              { $or: [{ invasive: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      req.query.endemic == 1 &&
      !req.query.invasive
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ endemic: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      req.query.endemic == 1 &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ endemic: { $in: [true] } }] },
              { $or: [{ invasive: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      !req.query.endangered &&
      !req.query.endemic &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              { $or: [{ invasive: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    } else if (
      req.query.endangered &&
      !req.query.endemic &&
      req.query.invasive == 1
    ) {
      try {
        const docs = await Specie.find(
          {
            $and: [
              { $or: [{ species: { $regex: regEx } }] },
              {
                $or: [
                  {
                    iucn: {
                      $in: ['EN', 'LC', 'VU', 'CR', 'NT']
                    }
                  }
                ]
              },
              { $or: [{ invasive: { $in: [true] } }] },
              {
                $or: [
                  {
                    bmClass: {
                      $in: [
                        req.query.bmClass1,
                        req.query.bmClass2,
                        req.query.bmClass3,
                        req.query.bmClass4,
                        req.query.bmClass5,
                        req.query.bmClass6,
                        req.query.bmClass7
                      ]
                    }
                  }
                ]
              }
            ]
          },
          {
            _id: 0,
            species: 1,
            taxID: 1,
            taxonomicStatus: 1,
            iucn: 1,
            bmClass: 1,
            endemic: 1,
            invasive: 1
          }
        );
        res.json(docs);
      } catch (err) {
        res.json(err);
      }
    }
  }
}
<commit_msg>Update search all species with additional conditions<commit_after>import GeoJSON from 'geojson';
import { Record } from '../../models/record.model';
import Specie from '../../models/specie.model';

function constructQuery(req) {
  const bmClass = {
    $or: [
      {
        bmClass: {
          $in: req.query.bmClass
        }
      }
    ]
  };
  const endemic = { $or: [{ endemic: { $in: [true] } }] };
  const invasive = { $or: [{ invasive: { $in: [true] } }] };
  const endangered = {
    $or: [
      {
        iucn: {
          $in: ['EN', 'LC', 'VU', 'CR', 'NT']
        }
      }
    ]
  };
  const query = {};
  if (
    req.params.species ||
    req.query.bmClass ||
    req.query.endangered ||
    req.query.endemic ||
    req.query.invasive
  ) {
    query.$and = [];
    if (req.query.bmClass) query.$and.push(bmClass);
    if (req.query.endangered) query.$and.push(endangered);
    if (req.query.endemic) query.$and.push(endemic);
    if (req.query.invasive) query.$and.push(invasive);
  }
  return query;
}

/**
 * @swagger
 * /species/records/{taxID}:
 *   get:
 *     description: "All the records of an acceptedNameUsage (using internal taxID as key): query (use = true & visualizationPrivileges = 0)"
 *     operationId: REC1
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function read(req, res) {
  if (req.params.taxID) {
    try {
      const docs = await Record.aggregate([
        {
          $match: {
            taxID: +req.params.taxID,
            use: true,
            visualizationPrivileges: 0,
            spatialDuplicated: false
          }
        },
        {
          $project: {
            reported: {
              $cond: {
                if: {
                  $and: [{ $isArray: '$reported' }, { $ne: ['$reported', []] }]
                },
                then: { $isArray: '$reported' },
                else: false
              }
            },
            updated: {
              $cond: {
                if: {
                  $and: [{ $isArray: '$updated' }, { $ne: ['$updated', []] }]
                },
                then: { $isArray: '$updated' },
                else: false
              }
            },
            _id: 1,
            taxID: 1,
            acceptedNameUsage: 1,
            species: 1,
            speciesOriginal: 1,
            locality: 1,
            lat: 1,
            lon: 1,
            alt: 1,
            basisOfRecord: 1,
            catalogNumber: 1,
            collector: 1,
            institution: 1,
            url: 1,
            dd: 1,
            mm: 1,
            yyyy: 1,
            suggestedStateProvince: 1,
            suggestedCounty: 1,
            environmentalOutlier: 1,
            source: 1
          }
        }
      ]);
      res.send(GeoJSON.parse(docs, { Point: ['lat', 'lon'] }));
    } catch (err) {
      res.send(err);
    }
  }
}

/**
 * @swagger
 * /species:
 *   get:
 *     description: "Get all the species in BioModelos"
 *     operationId: SPE1
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function getAllSpecies(req, res) {
  const query = constructQuery(req);
  try {
    const docs = await Specie.find(query, {
      species: 1,
      taxID: 1,
      _id: 0
    }).sort({ species: 1 });
    res.json(docs);
  } catch (err) {
    res.json(err);
  }
}

/**
 * @swagger
 * /species/{taxID}:
 *   get:
 *     description: "Get superior taxonomy and the total of records of a species"
 *     operationId: SPE2
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function getTaxonomyAndRecords(req, res) {
  if (req.params.taxID) {
    try {
      const doc = await Specie.find(
        { taxID: +req.params.taxID },
        {
          _id: 0,
          acceptedNameUsage: 1,
          species: 1,
          kingdom: 1,
          phylum: 1,
          class: 1,
          order: 1,
          family: 1
        }
      );
      try {
        const doc2 = await Record.aggregate([
          {
            $match: {
              taxID: +req.params.taxID,
              use: true,
              spatialDuplicated: false
            }
          },
          {
            $group: {
              _id: {
                characteristics: { taxID: '$taxID' }
              },
              totalRecords: { $sum: 1 }
            }
          },
          {
            $project: {
              _id: 0,
              taxID: '$_id.characteristics.taxID',
              totalRecords: '$totalRecords'
            }
          }
        ]);
        if (doc2[0] && doc2[0].totalRecords) {
          doc[0]['_doc']['totalRecords'] = doc2[0].totalRecords;
        } else {
          doc[0]['_doc']['totalRecords'] = 0;
        }
        res.json(doc);
      } catch (err) {
        res.json(err);
      }
    } catch (err) {
      res.json(err);
    }
  }
}

/**
 * @swagger
 * /species/search/{species}:
 *   get:
 *     description: "Get general query to obtain species with some specific characteristics"
 *     operationId: SPE3
 *     parameters:
 *       - name: taxID
 *         in: path
 *         description: The taxon ID of the specie
 *         required: true
 *         type: string
 *     responses:
 *       "200":
 *         description: Success
 *         schema:
 *           type: object
 *           required:
 *             - type
 *             - features
 *           properties:
 *             type:
 *               type: string
 *               default: "FeatureCollection"
 *             features:
 *               type: array
 *               items:
 *                 $ref: "#/definitions/FeatureSpecieRecord"
 *     default:
 *       description: Error
 *       schema:
 *         $ref: "#/definitions/ErrorResponse"
 */
export async function searchSpecie(req, res) {
  const query = constructQuery(req);
  if (req.params.species) {
    const regEx = new RegExp(req.params.species, 'ig');
    query.$and.push({ species: { $regex: regEx } });
  }
  try {
    const docs = await Specie.find(query, {
      _id: 0,
      species: 1,
      taxID: 1,
      taxonomicStatus: 1,
      iucn: 1,
      bmClass: 1,
      endemic: 1,
      invasive: 1
    });
    res.json(docs);
  } catch (err) {
    res.json(err);
  }
}
<|endoftext|>


<commit_before>var express    = require('express'),
    fs   = require('fs'),
    path = require('path'),
    app  = express(),
    indexPath = 'public/index.html',
    filePath = 'public/file.txt',
    pipe = require('pipe-io');

app.get('/', function(req, res) {
  sendFileWithPipe(indexPath, res);
});

app.get('/file', function (req, res) {
  sendFileWithPipe(filePath, res);
});

app.put('/file', function (req, res) {
  pipe([req, fs.createWriteStream(filePath, {'flags': 'a'})], function (error) {
    if (error)
      res.send(error.message).end();
  });
});

function sendFileWithPipe(filePath, responseStream) {
  var readStream = fs.createReadStream(filePath);
  pipe([readStream, responseStream], function (error) {
    if (error)
      responseStream.send(error.message).end();
  });
}

console.log('Server is listening 3000 port. Enjoy :).')
app.listen(3000);<commit_msg>update<commit_after>var express    = require('express'),
    fs   = require('fs'),
    path = require('path'),
    app  = express(),
    indexPath = 'public/index.html',
    filePath = 'public/file.txt',
    pipe = require('pipe-io');

app.get('/', function(req, res) {
  sendFileWithPipe(indexPath, res);
});

app.get('/file', function (req, res) {
  sendFileWithPipe(filePath, res);
});

app.put('/file', function (req, res) {
  pipe([req, fs.createWriteStream(filePath, {'flags': 'a'})], function (error) {
    if (error)
      res.status(500).send(error.message).end();
  });
});

function sendFileWithPipe(filePath, responseStream) {
  var readStream = fs.createReadStream(filePath);
  pipe([readStream, responseStream], function (error) {
    if (error)
      responseStream.send(error.message).end();
  });
}

console.log('Server is listening 3000 port. Enjoy :).')
app.listen(3000);<|endoftext|>


<commit_before>var express    = require('express'),
    fs   = require('fs'),
    path = require('path'),
    app  = express(),
    indexPath = 'public/index.html',
    filePath = 'public/file.txt',
    pipe = require('pipe-io');

app.get('/', function(req, res) {
  sendFileWithPipe(indexPath, res);
});

app.get('/file', function (req, res) {
  sendFileWithPipe(filePath, res);
});

app.put('/file', function (req, res) {
  pipe([req, fs.createWriteStream(filePath, {'flags': 'a'})], function (error) {
    if (error)
      res.status(500).send(error.message);
    else
      res.send('success')
  });
});

function sendFileWithPipe(filePath, responseStream) {
  var readStream = fs.createReadStream(filePath);
  pipe([readStream, responseStream], function (error) {
    if (error)
      responseStream.send(error.message);
  });
}

console.log('Server is listening 3000 port. Enjoy :).')
app.listen(3000);<commit_msg>add status 500<commit_after>var express    = require('express'),
    fs   = require('fs'),
    path = require('path'),
    app  = express(),
    indexPath = 'public/index.html',
    filePath = 'public/file.txt',
    pipe = require('pipe-io');

app.get('/', function(req, res) {
  sendFileWithPipe(indexPath, res);
});

app.get('/file', function (req, res) {
  sendFileWithPipe(filePath, res);
});

app.put('/file', function (req, res) {
  pipe([req, fs.createWriteStream(filePath, {'flags': 'a'})], function (error) {
    if (error)
      res.status(500).send(error.message);
    else
      res.send('success')
  });
});

function sendFileWithPipe(filePath, responseStream) {
  var readStream = fs.createReadStream(filePath);
  pipe([readStream, responseStream], function (error) {
    if (error)
      responseStream.status(500).send(error.message);
  });
}

console.log('Server is listening 3000 port. Enjoy :).')
app.listen(3000);<|endoftext|>


<commit_before>import angular from 'angular';
import _ from 'underscore';
import template from './compare.html';
import './compare.scss';

export function StatRangeFilter() {
  // Turns a stat and a list of ranges into a 0-100 scale
  return function(stat, statRanges) {
    if (!stat) {
      return -1;
    }
    const statRange = statRanges[stat.statHash];
    if (stat.qualityPercentage) {
      return stat.qualityPercentage.min;
    }

    if (!statRange.enabled) {
      return -1;
    }

    return 100 * (stat.value - statRange.min) / (statRange.max - statRange.min);
  };
}

export const CompareComponent = {
  controller: CompareCtrl,
  controllerAs: 'vm',
  template
};

function CompareCtrl($scope, toaster, dimCompareService, dimStoreService, D2StoresService, $i18next) {
  'ngInject';

  const vm = this;

  function getStoreService(item) {
    return item.destinyVersion === 2 ? D2StoresService : dimStoreService;
  }

  function addMissingStats(item) {
    if (!vm.comparisons[0]) {
      item.stats.forEach((stat, idx) => {
        vm.statsMap[stat.id] = idx;
      });
      return item;
    }
    const itemStatsMap = {};
    item.stats.forEach((stat, idx) => {
      itemStatsMap[stat.id] = { index: idx, name: stat.name };
    });

    _.difference(_.keys(vm.statsMap), _.keys(itemStatsMap)).forEach((statId) => {
      item.stats.splice(vm.statsMap[statId], 0, { value: undefined, id: Number(statId), statHash: Number(statId) });
    });

    _.difference(_.keys(itemStatsMap), _.keys(vm.statsMap)).forEach((statId) => {
      _.keys(vm.statsMap).forEach((statMapId) => {
        if (vm.statsMap[statMapId] >= itemStatsMap[statId].index) {
          vm.statsMap[statMapId]++;
        }
      });
      vm.statsMap[statId] = itemStatsMap[statId].index;
      vm.comparisons[0].stats.splice(vm.statsMap[statId], 0, { value: undefined, id: Number(statId), statHash: Number(statId), name: itemStatsMap[statId].name });
    });

    return item;
  }

  vm.show = dimCompareService.dialogOpen;

  vm.comparisons = [];
  vm.statRanges = {};
  vm.statsMap = {};

  $scope.$on('dim-store-item-compare', (event, args) => {
    vm.show = true;
    dimCompareService.dialogOpen = true;

    vm.add(args);
  });

  vm.cancel = function cancel() {
    vm.comparisons = [];
    vm.statRanges = {};
    vm.statsMap = {};
    vm.similarTypes = [];
    vm.archeTypes = [];
    vm.highlight = null;
    vm.sortedHash = null;
    vm.show = false;
    dimCompareService.dialogOpen = false;
  };

  vm.compareSimilar = function(type) {
    vm.comparisons = type === 'archetype' ? vm.archeTypes : vm.similarTypes;
  };

  vm.sort = function(statHash) {
    vm.sortedHash = statHash;
    vm.comparisons = _.sortBy(_.sortBy(_.sortBy(vm.comparisons, 'index'), 'name').reverse(), (item) => {
      const stat = _.find(item.stats, { statHash: statHash }) || item.primStat;
      return stat.value || -1;
    }).reverse();
  };

  vm.add = function add(args) {
    if (!args.item.equipment) {
      return;
    }

    if (vm.comparisons.length && vm.comparisons[0].typeName && args.item.typeName !== vm.comparisons[0].typeName) {
      if (vm.comparisons[0].classType && args.item.classType !== vm.comparisons[0].classType) {
        toaster.pop('warning', args.item.name, $i18next.t('Compare.Error.Class', { class: vm.comparisons[0].classTypeNameLocalized }));
        return;
      }
      toaster.pop('warning', args.item.name, $i18next.t('Compare.Error.Archetype', { type: vm.comparisons[0].typeName }));
      return;
    }

    if (args.dupes) {
      vm.compare = args.item;
      const allItems = getStoreService(args.item).getAllItems();
      vm.similarTypes = _.filter(allItems, { typeName: vm.compare.typeName });
      let armorSplit;
      if (!vm.compare.location.inWeapons) {
        vm.similarTypes = _.filter(vm.similarTypes, { classType: vm.compare.classType });
        armorSplit = _.reduce(vm.compare.stats, (memo, stat) => {
          return memo + (stat.base === 0 ? 0 : stat.statHash);
        }, 0);
      }

      // 4284893193 is RPM in D2
      const archetypeStat = _.find(vm.compare.stats, {
        statHash: (vm.compare.destinyVersion === 1
          ? vm.compare.stats[0].statHash
          : 4284893193)
      });
      if (archetypeStat) {
        vm.archeTypes = _.filter(vm.similarTypes, (item) => {
          if (item.location.inWeapons) {
            const archetypeMatch = _.find(item.stats, {
              statHash: (vm.compare.destinyVersion === 1
                ? vm.compare.stats[0].statHash
                : 4284893193)
            });
            if (!archetypeMatch) {
              return false;
            }
            return archetypeMatch.base === archetypeStat.base;
          }
          return _.reduce(item.stats, (memo, stat) => {
            return memo + (stat.base === 0 ? 0 : stat.statHash);
          }, 0) === armorSplit;
        });
      }
      vm.comparisons = _.map(_.filter(allItems, { hash: vm.compare.hash }), (item) => addMissingStats(item));
    } else if (!_.findWhere(vm.comparisons, { hash: args.item.hash, id: args.item.id })) {
      addMissingStats(args.item);
      vm.comparisons.push(args.item);
    }
  };

  vm.remove = function remove(item) {
    vm.comparisons = vm.comparisons.filter((compare) => {
      return compare.index !== item.index;
    });

    if (!vm.comparisons.length) {
      vm.cancel();
    }
  };

  vm.itemClick = function itemClick(item) {
    const element = angular.element(document.getElementById(item.index));
    const elementRect = element[0].getBoundingClientRect();
    const absoluteElementTop = elementRect.top + window.pageYOffset;
    window.scrollTo(0, absoluteElementTop - 150);
    element.addClass('item-pop');
    element.on('webkitAnimationEnd oanimationend msAnimationEnd animationend', () => {
      element.removeClass('item-pop');
    });
  };

  $scope.$watch('vm.comparisons', () => {
    const statBuckets = {};

    function bucketStat(stat) {
      if (stat && stat.value) {
        (statBuckets[stat.statHash] = statBuckets[stat.statHash] || []).push(stat.value);
      }
    }

    vm.comparisons.forEach((item) => {
      if (item.stats) {
        item.stats.forEach(bucketStat);
        bucketStat(item.primStat);
      }
    });

    vm.statRanges = {};
    _.each(statBuckets, (bucket, hash) => {
      const statRange = {
        min: Math.min(...bucket),
        max: Math.max(...bucket)
      };
      statRange.enabled = statRange.min !== statRange.max;
      vm.statRanges[hash] = statRange;
    });
  }, true);
}
<commit_msg>fix inconsistency adding stats<commit_after>import angular from 'angular';
import _ from 'underscore';
import template from './compare.html';
import './compare.scss';

export function StatRangeFilter() {
  // Turns a stat and a list of ranges into a 0-100 scale
  return function(stat, statRanges) {
    if (!stat) {
      return -1;
    }
    const statRange = statRanges[stat.statHash];
    if (stat.qualityPercentage) {
      return stat.qualityPercentage.min;
    }

    if (!statRange.enabled) {
      return -1;
    }

    return 100 * (stat.value - statRange.min) / (statRange.max - statRange.min);
  };
}

export const CompareComponent = {
  controller: CompareCtrl,
  controllerAs: 'vm',
  template
};

function CompareCtrl($scope, toaster, dimCompareService, dimStoreService, D2StoresService, $i18next) {
  'ngInject';

  const vm = this;

  function getStoreService(item) {
    return item.destinyVersion === 2 ? D2StoresService : dimStoreService;
  }

  function addMissingStats(item) {
    if (!vm.comparisons[0]) {
      item.stats.forEach((stat, idx) => {
        vm.statsMap[stat.id] = idx;
      });
      return item;
    }
    const itemStatsMap = {};
    item.stats.forEach((stat, idx) => {
      itemStatsMap[stat.id] = { index: idx, name: stat.name };
    });

    _.difference(_.keys(vm.statsMap), _.keys(itemStatsMap)).forEach((statId) => {
      item.stats.splice(vm.statsMap[statId], 0, { value: undefined, id: Number(statId), statHash: Number(statId) });
    });

    _.difference(_.keys(itemStatsMap), _.keys(vm.statsMap)).forEach((statId) => {
      _.keys(vm.statsMap).forEach((statMapId) => {
        if (vm.statsMap[statMapId] >= itemStatsMap[statId].index) {
          vm.statsMap[statMapId]++;
        }
      });
      vm.statsMap[statId] = itemStatsMap[statId].index;

      const missingStatItemIdx = vm.comparisons.findIndex((compItem) => !compItem.stats.some((stat) => stat.id === Number(statId)));
      if (item.hash === 2208405142) { debugger; }
      if (missingStatItemIdx > 0) {
        if (item.hash === 2208405142) { debugger; }
        vm.comparisons[missingStatItemIdx].stats.splice(vm.statsMap[statId], 0, { value: undefined, id: Number(statId), statHash: Number(statId), name: itemStatsMap[statId].name });
      }
    });

    if (item.hash === 2208405142) { debugger; }
    return item;
  }

  vm.show = dimCompareService.dialogOpen;

  vm.comparisons = [];
  vm.statRanges = {};
  vm.statsMap = {};

  $scope.$on('dim-store-item-compare', (event, args) => {
    vm.show = true;
    dimCompareService.dialogOpen = true;

    vm.add(args);
  });

  vm.cancel = function cancel() {
    vm.comparisons = [];
    vm.statRanges = {};
    vm.statsMap = {};
    vm.similarTypes = [];
    vm.archeTypes = [];
    vm.highlight = null;
    vm.sortedHash = null;
    vm.show = false;
    dimCompareService.dialogOpen = false;
  };

  vm.compareSimilar = function(type) {
    vm.comparisons = type === 'archetype' ? vm.archeTypes : vm.similarTypes;
  };

  vm.sort = function(statHash) {
    vm.sortedHash = statHash;
    vm.comparisons = _.sortBy(_.sortBy(_.sortBy(vm.comparisons, 'index'), 'name').reverse(), (item) => {
      const stat = _.find(item.stats, { statHash: statHash }) || item.primStat;
      return stat.value || -1;
    }).reverse();
  };

  vm.add = function add(args) {
    if (!args.item.equipment) {
      return;
    }

    if (vm.comparisons.length && vm.comparisons[0].typeName && args.item.typeName !== vm.comparisons[0].typeName) {
      if (vm.comparisons[0].classType && args.item.classType !== vm.comparisons[0].classType) {
        toaster.pop('warning', args.item.name, $i18next.t('Compare.Error.Class', { class: vm.comparisons[0].classTypeNameLocalized }));
        return;
      }
      toaster.pop('warning', args.item.name, $i18next.t('Compare.Error.Archetype', { type: vm.comparisons[0].typeName }));
      return;
    }

    if (args.dupes) {
      vm.compare = args.item;
      const allItems = getStoreService(args.item).getAllItems();
      vm.similarTypes = _.filter(allItems, { typeName: vm.compare.typeName });
      let armorSplit;
      if (!vm.compare.location.inWeapons) {
        vm.similarTypes = _.filter(vm.similarTypes, { classType: vm.compare.classType });
        armorSplit = _.reduce(vm.compare.stats, (memo, stat) => {
          return memo + (stat.base === 0 ? 0 : stat.statHash);
        }, 0);
      }

      // 4284893193 is RPM in D2
      const archetypeStat = _.find(vm.compare.stats, {
        statHash: (vm.compare.destinyVersion === 1
          ? vm.compare.stats[0].statHash
          : 4284893193)
      });
      if (archetypeStat) {
        vm.archeTypes = _.filter(vm.similarTypes, (item) => {
          if (item.location.inWeapons) {
            const archetypeMatch = _.find(item.stats, {
              statHash: (vm.compare.destinyVersion === 1
                ? vm.compare.stats[0].statHash
                : 4284893193)
            });
            if (!archetypeMatch) {
              return false;
            }
            return archetypeMatch.base === archetypeStat.base;
          }
          return _.reduce(item.stats, (memo, stat) => {
            return memo + (stat.base === 0 ? 0 : stat.statHash);
          }, 0) === armorSplit;
        });
      }
      vm.comparisons = _.map(_.filter(allItems, { hash: vm.compare.hash }), (item) => addMissingStats(item));
    } else if (!_.findWhere(vm.comparisons, { hash: args.item.hash, id: args.item.id })) {
      addMissingStats(args.item);
      vm.comparisons.push(args.item);
    }
  };

  vm.remove = function remove(item) {
    vm.comparisons = vm.comparisons.filter((compare) => {
      return compare.index !== item.index;
    });

    if (!vm.comparisons.length) {
      vm.cancel();
    }
  };

  vm.itemClick = function itemClick(item) {
    const element = angular.element(document.getElementById(item.index));
    const elementRect = element[0].getBoundingClientRect();
    const absoluteElementTop = elementRect.top + window.pageYOffset;
    window.scrollTo(0, absoluteElementTop - 150);
    element.addClass('item-pop');
    element.on('webkitAnimationEnd oanimationend msAnimationEnd animationend', () => {
      element.removeClass('item-pop');
    });
  };

  $scope.$watch('vm.comparisons', () => {
    const statBuckets = {};

    function bucketStat(stat) {
      if (stat && stat.value) {
        (statBuckets[stat.statHash] = statBuckets[stat.statHash] || []).push(stat.value);
      }
    }

    vm.comparisons.forEach((item) => {
      addMissingStats(item);
      if (item.stats) {
        item.stats.forEach(bucketStat);
        bucketStat(item.primStat);
      }
    });

    vm.statRanges = {};
    _.each(statBuckets, (bucket, hash) => {
      const statRange = {
        min: Math.min(...bucket),
        max: Math.max(...bucket)
      };
      statRange.enabled = statRange.min !== statRange.max;
      vm.statRanges[hash] = statRange;
    });
  }, true);
}
<|endoftext|>


<commit_before>$(document).ready(function(){
	var refresh = $("#inptRefresh").val();
	refresh = (refresh * 1000);
	$("#add_widget").button();

	$("#tabs").tabs({ // First, Initialize tabs and the tab template
		tabTemplate: '
#{label} Remove Tab
',
		load: function(event, ui){ // When the tab is loaded
			add_features();  // Add features
		},
		select: function(event, ui){ // When a tab is selected
			//var index = $( '#tabs' ).tabs('option', 'selected');
			//alert(index);
			//if(index !=0) $("#monitors").remove(); // Remove old monitors
		}
	});

	load_tabs(); // Then load the tabs into #tabs
	add_tab_click(); // Finally, setup the add tab feature

	function load_tabs() {
		tab_all_load('skins/modern/views/monitors-view.php?width='+$("#monitors").width() );

		$.post("skins/modern/includes/updateGroups.php?action=select", function(data) { // Load tabs (groups)
			saved_tabs = data.split(",");
			saved_tabs.pop();
			var x = saved_tabs.length;
			for (var i=0;i<x;i++) {
				var name = saved_tabs[i];
				$("#tabs").tabs('add', 'skins/modern/views/monitors.php?groupName='+name, name); // Add the tab
			}
			init_delete_tab();
		});
	};

	function init_delete_tab() {
	// close icon: removing the tab on click
	// note: closable tabs gonna be an option in the future - see http://dev.jqueryui.com/ticket/3924
		$('#tabs .ui-icon-close').click(function() {
			var index = $('li',$("#tabs")).index($(this).parent());
			alert(index);
			if(index != 0) {
				$.post("skins/modern/includes/updateGroups.php?action=delete&groupName=" + $(this).parent().find('a').text());
				$("#tabs").tabs('remove', index);
			}
		});
	}

	function add_features() {
		// This function is called whenever cameras are loaded (via the tab load event)
		// It setups up Minimize, Sortable, Colorbox features for the newly-loaded monitors
		$(".minimize").click(function() { // Minimize
		$(this).parent().parent().parent().find('.mon').toggle('blind');
		});

		$(".maximize").click(function() {
			if($(this).parent().parent().parent().find('.mon').is(":visible")) {
			//alert($(this).attr('url'));
			jQuery.colorbox({
				href:$(this).attr('url'),
				iframe:true,
				width:'85%',
				height:'95%',
				open:true
			});
		} else {
		$(this).parent().parent().parent().find('.mon').toggle('blind');
		}
		});

		$("#monitors").sortable({ opacity: 0.6, cursor: 'move', update: function() { // Sortable
		var order = $(this).sortable("serialize") + '&action=sequence';
		$.post("skins/modern/includes/updateSequence.php", order);
		}});

		$("a[rel='monitor']").colorbox({ // Colorbox
			iframe:true,
			preloading:false,
			current:'{current} of {total}',
			width:'85%',
			height:'95%'
		});
	 };  // END ADD_FEATURES //

	 function add_tab_click() { // Call this last
	  // This whole shabang is used for adding tabs.
	  // We get the tab title and contents, setup the dialog box, create the functions
	  // for adding the tab, deleting tab, closing and opening dialog box, etc.

	  var $tab_title_input = $('#tab_title'), $tab_content_input = $('#tab_content');

	  // modal dialog init: custom buttons and a "close" callback reseting the form inside
	  var $dialog = $('#dialog').dialog({
	   autoOpen: false,
	   modal: true,
	   buttons: {
	    'Add': function() {
	      addTab();
	      $(this).dialog('close');
	     },
	    'Cancel': function() {
	     $(this).dialog('close');
	    }
	   },
	   open: function() {
	    tab_title_input.focus();
	   }
	  }); // END DIALOG //

	  // addTab form: calls addTab function on submit and closes the dialog
	  var $form = $('form',$dialog).submit(function() {
	  addTab();
	  $dialog.dialog('close');
	  return false;
	 });

	  // actual addTab function: adds new tab using the title input from the form above
	  function addTab() {
	   tab_title = $tab_title_input.val(); // groupName
	   var arysel  = []; // An array for the monitorIds
	   $("#selMonitors :selected").each(function(i, selected) { // For each selected MonitorId
	    arysel[i] = $(selected).val(); // Put it into the array
	   });
	   var mids = arysel.toString(); // Make a comman-separated list of the select MonitorsIds
	   $.post("skins/modern/includes/updateGroups.php?groupName=" + tab_title + "&mids=" + mids + "&action=insert"); // Add the new Group
	   $("#tabs").tabs('add', 'skins/modern/views/monitors.php?groupName='+tab_title, tab_title); // Add the actual tab
	   init_delete_tab();
	  }

	  // addTab button: just opens the dialog
	  $('#add_tab').button().click(function() {
	   $dialog.dialog('open');
	  });

		$('#change_view').button().click(function() {
			$.colorbox({inline:true, innerWidth:800, innerHeight:520, href:'#viewcontrol'});
		});

		$('#refresh_monitors').button().click(function() {
			loadcameras()
		});

	 } // END ADD_TAB_CLICK() //

	/* setInterval(function() {
		$("#monitors li").each(function() {
		var _this = $(this);
		$(".spinner",_this).html("");
		var mid = $(this).attr("id");
		mid = mid.split("_");
		$(".mon",this).load("skins/modern/views/monitors.php?mid=" + mid[1] + " .mon", function () {
		$(".spinner",_this).fadeOut('slow');
		});
		});
		}, refresh);
	*/

	$.ajax({
		url: 'skins/modern/views/monitors-view.php?width='+$("#monitors").width(),
		success: function(data) {
			//console.log(data);
			$("ul#monitors").replaceWith(data);
		},
		async: false
	});

}); /* end document ready */

function tab_all_load(url) {
	console.log("tab_all_load()");
	//index = 0;//$( '#tabs' ).tabs('option', 'selected');
	//$( '#tabs' ).tabs( "url" , index , url ).tabs('load', index).tabs({ cache: true });
}

var camera_saved_state;
function loadcameras(options,callback) {
	is_loading_camaras = true;

	if(options == undefined) {
		if(camera_saved_state==undefined) camera_saved_state = {type:'columns',number:3};
		options = camera_saved_state;
	} else camera_saved_state = options;

	options['width'] = $("#monitors").width();
	options['aspectratio'] = ''; //$("#id-console-views-aspect-ratio").val()==undefined ? '' : $("#id-console-views-aspect-ratio").val();

	tab_all_load('skins/modern/views/monitors-view.php?'+$.param(options));
	$.colorbox.close()
}
function loadcameragrid(elem,size) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	loadcameras( {type:'columns',number:size},"changemonitor(0);" )
	$(elem).attr("disabled", "disabled");
	return false;
}
function loadcameramonitor(elem,mid) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	loadcameras({type:'monitor',monitorid:mid},"changemonitor(0);");
	$(elem).attr("disabled", "disabled");
	return false;
}
function loadcameraview(size) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	loadcameras({type:'view',number:size},"changemonitor(0);");

	$("#id-console-views-img-"+size).attr("src",skinPath+'/graphics/view_buttons/view_'+size+'_pressed.png');

}<commit_msg>Converted deprecated jQuery functions. Closing/deleting tabs now works.<commit_after>$(document).ready(function(){
	var refresh = $("#inptRefresh").val();
	refresh = (refresh * 1000);
	$("#add_widget").button();

	$("#tabs").tabs({ // First, Initialize tabs and the tab template
		tabTemplate: '
#{label} Remove Tab
',
		load: function(event, ui){ // When the tab is loaded
			add_features();  // Add features
		},
		select: function(event, ui){ // When a tab is selected
			//var index = $( '#tabs' ).tabs('option', 'selected');
			//alert(index);
			//if(index !=0) $("#monitors").remove(); // Remove old monitors
		}
	});

	load_tabs(); // Then load the tabs into #tabs
	add_tab_click(); // Finally, setup the add tab feature

	function load_tabs() {
		tab_all_load('skins/modern/views/monitors-view.php?width='+$("#monitors").width() );

		$.post("skins/modern/includes/updateGroups.php?action=select", function(data) { // Load tabs (groups)
			saved_tabs = data.split(",");
			saved_tabs.pop();
			var x = saved_tabs.length;
			for (var i=0;i<x;i++) {
				var name = saved_tabs[i];
				//$("#tabs").tabs('add', 'skins/modern/views/monitors.php?groupName='+name, name); // Add the tab
				$("
" + name + "
").appendTo("#tabs .ui-tabs-nav");
				$("#tabs").tabs("refresh");

			}

			$("").appendTo(".ui-state-default:last-child");

			init_delete_tab();
		});
	};

	function init_delete_tab() {
	// close icon: removing the tab on click
	// note: closable tabs gonna be an option in the future - see http://dev.jqueryui.com/ticket/3924
	// kjvarley: closing tabs will not be implemented by the official jqueryui team
	// kjvarley: I have implemented a close button feature with some code in this file
		$('#tabs .ui-icon-close').click(function() {
			var index = $('li',$("#tabs")).index($(this).parent());
			//alert(index);
			if(index != 0) {
				$.post("skins/modern/includes/updateGroups.php?action=delete&groupName=" + $(this).parent().find('a').text());
				var tab = $("#tabs").find(".ui-tabs-nav li:eq("+index+")").remove();
				var panelId = tab.attr("aria-controls");
				$("#"+panelId).remove();
				$("#tabs").tabs("refresh");
				//$("#tabs").tabs('remove', index);
			}
		});
	}

	function add_features() {
		// This function is called whenever cameras are loaded (via the tab load event)
		// It setups up Minimize, Sortable, Colorbox features for the newly-loaded monitors
		$(".minimize").click(function() { // Minimize
		$(this).parent().parent().parent().find('.mon').toggle('blind');
		});

		$(".maximize").click(function() {
			if($(this).parent().parent().parent().find('.mon').is(":visible")) {
			//alert($(this).attr('url'));
			jQuery.colorbox({
				href:$(this).attr('url'),
				iframe:true,
				width:'85%',
				height:'95%',
				open:true
			});
		} else {
		$(this).parent().parent().parent().find('.mon').toggle('blind');
		}
		});

		$("#monitors").sortable({ opacity: 0.6, cursor: 'move', update: function() { // Sortable
		var order = $(this).sortable("serialize") + '&action=sequence';
		$.post("skins/modern/includes/updateSequence.php", order);
		}});

		$("a[rel='monitor']").colorbox({ // Colorbox
			iframe:true,
			preloading:false,
			current:'{current} of {total}',
			width:'85%',
			height:'95%'
		});
	 };  // END ADD_FEATURES //

	 function add_tab_click() { // Call this last
	  // This whole shabang is used for adding tabs.
	  // We get the tab title and contents, setup the dialog box, create the functions
	  // for adding the tab, deleting tab, closing and opening dialog box, etc.

	  var $tab_title_input = $('#tab_title'), $tab_content_input = $('#tab_content');

	  // modal dialog init: custom buttons and a "close" callback reseting the form inside
	  var $dialog = $('#dialog').dialog({
	   autoOpen: false,
	   modal: true,
	   buttons: {
	    'Add': function() {
	      addTab();
	      $(this).dialog('close');
	     },
	    'Cancel': function() {
	     $(this).dialog('close');
	    }
	   },
	   open: function() {
	    tab_title_input.focus();
	   }
	  }); // END DIALOG //

	  // addTab form: calls addTab function on submit and closes the dialog
	  var $form = $('form',$dialog).submit(function() {
	  addTab();
	  $dialog.dialog('close');
	  return false;
	 });

	  // actual addTab function: adds new tab using the title input from the form above
	  function addTab() {
	   tab_title = $("#tab_title").val(); // groupName
	   var arysel  = []; // An array for the monitorIds
	   $("#selMonitors :selected").each(function(i, selected) { // For each selected MonitorId
	    arysel[i] = $(selected).val(); // Put it into the array
	   });
	   var mids = arysel.toString(); // Make a comman-separated list of the select MonitorsIds
	   $.post("skins/modern/includes/updateGroups.php?groupName=" + tab_title + "&mids=" + mids + "&action=insert"); // Add the new Group

	   //$("#tabs").tabs('add', 'skins/modern/views/monitors.php?groupName='+tab_title, tab_title); // Add the actual tab

	   $("
" + tab_title + "
").appendTo("#tabs .ui-tabs-nav");
		$("#tabs").tabs("refresh");

		init_close_tab();
	   init_delete_tab();
	  }

	  // addTab button: just opens the dialog
	  $('#add_tab').button().click(function() {
	    $dialog.dialog('open');
	  });

		$('#change_view').button().click(function() {
			$.colorbox({inline:true, innerWidth:800, innerHeight:520, href:'#viewcontrol'});
		});

		$('#refresh_monitors').button().click(function() {
			loadcameras()
		});

	 } // END ADD_TAB_CLICK() //

	/* setInterval(function() {
		$("#monitors li").each(function() {
		var _this = $(this);
		$(".spinner",_this).html("");
		var mid = $(this).attr("id");
		mid = mid.split("_");
		$(".mon",this).load("skins/modern/views/monitors.php?mid=" + mid[1] + " .mon", function () {
		$(".spinner",_this).fadeOut('slow');
		});
		});
		}, refresh);
	*/

	$.ajax({
		url: 'skins/modern/views/monitors-view.php?width='+$("#monitors").width(),
		success: function(data) {
			//console.log(data);
			$("ul#monitors").replaceWith(data);
		},
		async: false
	});

}); /* end document ready */

function init_close_tab() {
	$(".ui-tabs-anchor").each(function() {
		if($(this).text()!="All") {
			console.log($(this));
			if(($(this) + " > .ui-icon-close").length != 0) {
				$("").appendTo($(this).parent());
			}
		}
	});
}

function tab_all_load(url) {
	console.log("tab_all_load()");
	//index = 0;//$( '#tabs' ).tabs('option', 'selected');
	//$( '#tabs' ).tabs( "url" , index , url ).tabs('load', index).tabs({ cache: true });
}

var camera_saved_state;
function loadcameras(options,callback) {
	is_loading_camaras = true;

	if(options == undefined) {
		if(camera_saved_state==undefined) camera_saved_state = {type:'columns',number:3};
		options = camera_saved_state;
	} else camera_saved_state = options;

	options['width'] = $("#monitors").width();
	options['aspectratio'] = ''; //$("#id-console-views-aspect-ratio").val()==undefined ? '' : $("#id-console-views-aspect-ratio").val();

	tab_all_load('skins/modern/views/monitors-view.php?'+$.param(options));
	$.colorbox.close()
}
function loadcameragrid(elem,size) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	loadcameras( {type:'columns',number:size},"changemonitor(0);" )
	$(elem).attr("disabled", "disabled");
	return false;
}
function loadcameramonitor(elem,mid) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	loadcameras({type:'monitor',monitorid:mid},"changemonitor(0);");
	$(elem).attr("disabled", "disabled");
	return false;
}
function loadcameraview(size) {
	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	$("#id-console-views-img-1").attr("src",skinPath+'/graphics/view_buttons/view_1_unpressed.png');
	$("#id-console-views-img-4").attr("src",skinPath+'/graphics/view_buttons/view_4_unpressed.png');
	$("#id-console-views-img-6").attr("src",skinPath+'/graphics/view_buttons/view_6_unpressed.png');
	$("#id-console-views-img-8").attr("src",skinPath+'/graphics/view_buttons/view_8_unpressed.png');
	$("#id-console-views-img-9").attr("src",skinPath+'/graphics/view_buttons/view_9_unpressed.png');
	$("#id-console-views-img-10").attr("src",skinPath+'/graphics/view_buttons/view_10_unpressed.png');
	$("#id-console-views-img-13").attr("src",skinPath+'/graphics/view_buttons/view_13_unpressed.png');
	$("#id-console-views-img-16").attr("src",skinPath+'/graphics/view_buttons/view_16_unpressed.png');

	$(".btngridsize, .btnmonitor").removeAttr("disabled");
	loadcameras({type:'view',number:size},"changemonitor(0);");

	$("#id-console-views-img-"+size).attr("src",skinPath+'/graphics/view_buttons/view_'+size+'_pressed.png');

}<|endoftext|>


<commit_before>$(document).ready(function() {
    var droppedDown = false;
    var fileType = true;
	var converting = false;

	var fileTypes = ["wmv", "m4v", "mp4", "mp3"];

    if(typeof FileActions !== 'undefined') {
        var infoIconPath = OC.imagePath('convert','convert.svg');

        FileActions.register('file', 'Convert', OC.PERMISSION_UPDATE, infoIconPath, function(fileName) {
            var extension = fileName.substring(fileName.length - 5);

            if(scanFiles.scanning) { return; }

            var directory = $('#dir').val();
            directory = (directory === "/") ? directory : directory + "/";

            var filePath = directory + fileName;
            var message = t('convert', "Select file type:");

            //Build dropdown menu
            var html = '
\n\

' + message + '
\n\

\n\
                                <input id="fileType" style="width:220px" type="text" />\n\
                                <input id="execute" type="button" value="' + 'Convert' + '" />\n\

\n\

';

            if(fileName) {
                $('tr').filterAttr('data-file',fileName).addClass('mouseOver');
                $(html).appendTo($('tr').filterAttr('data-file', fileName).find('td.filename'));
            }

            $('#dropdown').show('blind');
            $('#convert_sel').chosen();
            $('#execute').bind('click',function() {
                if(fileType) {
                    var type = $('#fileType').val();
					var outPath = filePath.substr(0, filePath.lastIndexOf(".")) + "." + type;
                    doConvert(filePath, outPath);
                }
            });

            $('#fileType').bind('keyup', function(eventData) {
                var type = $('#fileType').val();
				var outPath = filePath.substr(0, filePath.lastIndexOf(".")) + "." + type;

                    fileType = true;

                    if(eventData.keyCode == 13) {
                        doConvert(filePath, outPath);
                    }

            });
        });

        droppedDown = true;
    }

    $(document).on('click', function(event) {
        var target = $(event.target);
        var clickOut = !(target.is('#fileType') || target.is('#execute'));

        if(droppedDown && clickOut && !converting) {
            hideDropDown();
        }
    });

	function getProgress(filePath) {
		$.get(OC.linkTo('convert', 'ajax/getprogress.php'), {filePath : filePath}, function( result ) {
			if (result == -1) {
				alert("Unable to read log file. No progress information available.");
				document.location.reload();
			}
			else if (result >= 100) {
				alert("Conversion complete.");
				document.location.reload();
			}
			else {
				updateProgress(result);
				setTimeout(getProgress(), 1000);
			}
		});
	}

	function updateProgress(result) {
		var progress = result;
		progress += "%";
		$('#submit').html('

' + progress + '

');
	}

    function doConvert(filePath, outPath) {
		converting = true;

		$.ajax({
            type    : 'POST',
            url     : OC.linkTo('convert', 'ajax/convert.php'),
            timeout : 0,
			async   : false,
            data    : {
                filePath    : filePath,
                outPath     : outPath
			}
        });

		getProgress();
    }

    function hideDropDown() {
        $('#dropdown').hide('blind',function(){
            $('#dropdown').remove();
            $('tr').removeClass('mouseOver');
        });
    }
});
<commit_msg>Dropdown<commit_after>$(document).ready(function() {
    var droppedDown = false;
    var fileType = true;
	var converting = false;

	var fileTypes = ["'wmv'", "'m4v'", "'mp4'", "'mp3'"];

    if(typeof FileActions !== 'undefined') {
        var infoIconPath = OC.imagePath('convert','convert.svg');

        FileActions.register('file', 'Convert', OC.PERMISSION_UPDATE, infoIconPath, function(fileName) {
            var extension = fileName.substring(fileName.length - 5);

            if(scanFiles.scanning) { return; }

            var directory = $('#dir').val();
            directory = (directory === "/") ? directory : directory + "/";

            var filePath = directory + fileName;
            var message = t('convert', "Select file type:");

            //Build dropdown menu
            var html = '
\n\

' + message + '
\n\

\n\
                                <input id="fileType" style="width:220px" type="text" />\n\
                                <input id="execute" type="button" value="' + 'Convert' + '" />\n\

\n\

';

            if(fileName) {
                $('tr').filterAttr('data-file',fileName).addClass('mouseOver');
                $(html).appendTo($('tr').filterAttr('data-file', fileName).find('td.filename'));
            }

            $('#dropdown').show('blind');
            $('#convert_sel').chosen();
            $('#execute').bind('click',function() {
                if(fileType) {
                    var type = $('#fileType').val();
					var outPath = filePath.substr(0, filePath.lastIndexOf(".")) + "." + type;
                    doConvert(filePath, outPath);
                }
            });

            $('#fileType').bind('keyup', function(eventData) {
                var type = $('#fileType').val();
				var outPath = filePath.substr(0, filePath.lastIndexOf(".")) + "." + type;

                    fileType = true;

                    if(eventData.keyCode == 13) {
                        doConvert(filePath, outPath);
                    }

            });
        });

        droppedDown = true;
    }

    $(document).on('click', function(event) {
        var target = $(event.target);
        var clickOut = !(target.is('#fileType') || target.is('#execute'));

        if(droppedDown && clickOut && !converting) {
            hideDropDown();
        }
    });

	function getProgress(filePath) {
		$.get(OC.linkTo('convert', 'ajax/getprogress.php'), {filePath : filePath}, function( result ) {
			if (result == -1) {
				alert("Unable to read log file. No progress information available.");
				document.location.reload();
			}
			else if (result >= 100) {
				alert("Conversion complete.");
				document.location.reload();
			}
			else {
				updateProgress(result);
				setTimeout(getProgress(), 1000);
			}
		});
	}

	function updateProgress(result) {
		var progress = result;
		progress += "%";
		$('#submit').html('

' + progress + '

');
	}

    function doConvert(filePath, outPath) {
		converting = true;

		$.ajax({
            type    : 'POST',
            url     : OC.linkTo('convert', 'ajax/convert.php'),
            timeout : 0,
			async   : false,
            data    : {
                filePath    : filePath,
                outPath     : outPath
			}
        });

		getProgress();
    }

    function hideDropDown() {
        $('#dropdown').hide('blind',function(){
            $('#dropdown').remove();
            $('tr').removeClass('mouseOver');
        });
    }
});
<|endoftext|>


<commit_before>/*
 *      This file is part of GPaste.
 *
 *      Copyright 2011-2012 Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 *
 *      GPaste is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      GPaste is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with GPaste.  If not, see <http://www.gnu.org/licenses/>.
 */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Pango = imports.gi.Pango;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Gettext = imports.gettext;
const GPaste = imports.gi.GPaste;

const _ = Gettext.domain('GPaste').gettext;
const BUS_NAME = 'org.gnome.GPaste';
const OBJECT_PATH = '/org/gnome/GPaste';

const GPasteIndicator = new Lang.Class({
    Name: 'GPasteIndicator',
    Extends: PanelMenu.Button,

    _init: function() {
        this.parent(0.0, "GPaste");

        this.actor.add_child(new St.Icon({
            icon_name: 'edit-paste-symbolic',
            style_class: 'system-status-icon'
        }));

        this._killSwitch = new PopupMenu.PopupSwitchMenuItem(_("Track changes"), true);
        this._killSwitch.connect('toggled', Lang.bind(this, this._toggleDaemon));
        this._client = new GPaste.Client();
        this._client.connect('changed', Lang.bind(this, this._updateHistory));
        this._client.connect('show-history', Lang.bind(this, this._showHistory));
        this._client.connect('tracking', Lang.bind(this, function(c, state) {
            this._killSwitch.setToggleState(state);
        }));
        this._createHistory();
        this._noHistory = new PopupMenu.PopupMenuItem("");
        this._noHistory.setSensitive(false);
        this._emptyHistory = new PopupMenu.PopupMenuItem(_("Empty history"));
        this._emptyHistory.connect('activate', Lang.bind(this, this._empty));
        this._fillMenu();
    },

    _select: function(index) {
        this._client.select(index);
    },

    _delete: function(index) {
        this._client.delete(index);
    },

    _empty: function() {
        this._client.empty();
    },

    _toggleDaemon: function() {
        this._client.track(this._killSwitch.state);
    },

    _fillMenu: function() {
        this._killSwitch.setToggleState(this._client.is_active());
        this.menu.addMenuItem(this._killSwitch);
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this._addHistoryItems();
        this.menu.addMenuItem(this._noHistory);
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this.menu.addMenuItem(this._emptyHistory);
        this.menu.addSettingsAction(_("GPaste daemon settings"), 'gpaste-settings.desktop');
        this._updateHistory();
    },

    _updateHistory: function() {
        let history = this._client.get_history();
        if (history != null && history.length != 0) {
            let limit = Math.min(history.length, this._history.length);
            for (let index = 0; index < limit; ++index)
                this._updateHistoryItem(index, history[index]);
            this._hideHistory(limit);
            this._noHistory.actor.hide();
            this._emptyHistory.actor.show();
        } else {
            this._noHistory.label.text = (history == null) ? _("(Couldn't connect to GPaste daemon)") : _("(Empty)");
            this._hideHistory();
            this._emptyHistory.actor.hide();
            this._noHistory.actor.show();
        }
    },

    _showHistory: function() {
        this.menu.open(true);
        this.menu.firstMenuItem.setActive(true);
    },

    _createHistoryItem: function(index) {
        let item = new PopupMenu.PopupMenuItem("");
        let text = item.label.clutter_text;
        text.max_length = 60;
        text.ellipsize = Pango.EllipsizeMode.END;
        item.connect('activate', Lang.bind(this, function(actor, event) {
            this._select(index);
        }));
        item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
            let symbol = event.get_key_symbol();
            if (symbol == Clutter.KEY_BackSpace || symbol == Clutter.KEY_Delete) {
                this._delete(index);
                return true;
            }
            return false;
        }));
        let deleteItem = new St.Button();
        deleteItem.child = new St.Icon({
            icon_name: 'edit-delete-symbolic',
            style_class: 'system-status-icon'
        });
        deleteItem.connect('clicked', Lang.bind(this, function(actor, event) {
            this._delete(index);
            return true;
        }));
        item.actor.insert_child_at_index(deleteItem, item.actor.get_n_children() - 1);
        return item;
    },

    _createHistory: function() {
        this._history = [];
        for (let index = 0; index < 20; ++index)
            this._history[index] = this._createHistoryItem(index);
        this._history[0].label.set_style("font-weight: bold;");
    },

    _addHistoryItems: function() {
        for (let index = 0; index < this._history.length; ++index)
            this.menu.addMenuItem(this._history[index]);
    },

    _updateHistoryItem: function(index, element) {
        let displayStr = element.replace(/\n/g, ' ');
        let altDisplayStr = _("delete: %s").format(displayStr);
        this._history[index].label.set_text (displayStr);
        this._history[index].actor.show();
    },

    _hideHistory: function(startIndex) {
        for (let index = startIndex || 0; index < this._history.length; ++index)
            this._history[index].actor.hide();
    },

    _onStateChanged: function (state) {
        this._client.on_extension_state_changed(state);
    }
});

let _indicator;

function init(extension) {
    Gettext.bindtextdomain('gpaste', extension.metadata.localedir);
}

function enable() {
    _indicator = new GPasteIndicator();
    _indicator._onStateChanged (true);
    Main.panel.addToStatusArea('gpaste', _indicator);
}

function disable() {
    _indicator._onStateChanged (false);
    _indicator.destroy();
}

<commit_msg>gnome-shell: add fancy little arrow<commit_after>/*
 *      This file is part of GPaste.
 *
 *      Copyright 2011-2012 Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 *
 *      GPaste is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      GPaste is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with GPaste.  If not, see <http://www.gnu.org/licenses/>.
 */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Pango = imports.gi.Pango;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Gettext = imports.gettext;
const GPaste = imports.gi.GPaste;

const _ = Gettext.domain('GPaste').gettext;
const BUS_NAME = 'org.gnome.GPaste';
const OBJECT_PATH = '/org/gnome/GPaste';

const GPasteIndicator = new Lang.Class({
    Name: 'GPasteIndicator',
    Extends: PanelMenu.Button,

    _init: function() {
        this.parent(0.0, "GPaste");

        let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
        hbox.add_child(new St.Icon({
            icon_name: 'edit-paste-symbolic',
            style_class: 'system-status-icon'
        }));
        hbox.add_child(new St.Label({
            text: '\u25BE',
            y_expand: true,
            y_align: Clutter.ActorAlign.CENTER
        }));
        this.actor.add_child(hbox);

        this._killSwitch = new PopupMenu.PopupSwitchMenuItem(_("Track changes"), true);
        this._killSwitch.connect('toggled', Lang.bind(this, this._toggleDaemon));
        this._client = new GPaste.Client();
        this._client.connect('changed', Lang.bind(this, this._updateHistory));
        this._client.connect('show-history', Lang.bind(this, this._showHistory));
        this._client.connect('tracking', Lang.bind(this, function(c, state) {
            this._killSwitch.setToggleState(state);
        }));
        this._createHistory();
        this._noHistory = new PopupMenu.PopupMenuItem("");
        this._noHistory.setSensitive(false);
        this._emptyHistory = new PopupMenu.PopupMenuItem(_("Empty history"));
        this._emptyHistory.connect('activate', Lang.bind(this, this._empty));
        this._fillMenu();
    },

    _select: function(index) {
        this._client.select(index);
    },

    _delete: function(index) {
        this._client.delete(index);
    },

    _empty: function() {
        this._client.empty();
    },

    _toggleDaemon: function() {
        this._client.track(this._killSwitch.state);
    },

    _fillMenu: function() {
        this._killSwitch.setToggleState(this._client.is_active());
        this.menu.addMenuItem(this._killSwitch);
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this._addHistoryItems();
        this.menu.addMenuItem(this._noHistory);
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this.menu.addMenuItem(this._emptyHistory);
        this.menu.addSettingsAction(_("GPaste daemon settings"), 'gpaste-settings.desktop');
        this._updateHistory();
    },

    _updateHistory: function() {
        let history = this._client.get_history();
        if (history != null && history.length != 0) {
            let limit = Math.min(history.length, this._history.length);
            for (let index = 0; index < limit; ++index)
                this._updateHistoryItem(index, history[index]);
            this._hideHistory(limit);
            this._noHistory.actor.hide();
            this._emptyHistory.actor.show();
        } else {
            this._noHistory.label.text = (history == null) ? _("(Couldn't connect to GPaste daemon)") : _("(Empty)");
            this._hideHistory();
            this._emptyHistory.actor.hide();
            this._noHistory.actor.show();
        }
    },

    _showHistory: function() {
        this.menu.open(true);
        this.menu.firstMenuItem.setActive(true);
    },

    _createHistoryItem: function(index) {
        let item = new PopupMenu.PopupMenuItem("");
        let text = item.label.clutter_text;
        text.max_length = 60;
        text.ellipsize = Pango.EllipsizeMode.END;
        item.connect('activate', Lang.bind(this, function(actor, event) {
            this._select(index);
        }));
        item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
            let symbol = event.get_key_symbol();
            if (symbol == Clutter.KEY_BackSpace || symbol == Clutter.KEY_Delete) {
                this._delete(index);
                return true;
            }
            return false;
        }));
        let deleteItem = new St.Button();
        deleteItem.child = new St.Icon({
            icon_name: 'edit-delete-symbolic',
            style_class: 'system-status-icon'
        });
        deleteItem.connect('clicked', Lang.bind(this, function(actor, event) {
            this._delete(index);
            return true;
        }));
        item.actor.insert_child_at_index(deleteItem, item.actor.get_n_children() - 1);
        return item;
    },

    _createHistory: function() {
        this._history = [];
        for (let index = 0; index < 20; ++index)
            this._history[index] = this._createHistoryItem(index);
        this._history[0].label.set_style("font-weight: bold;");
    },

    _addHistoryItems: function() {
        for (let index = 0; index < this._history.length; ++index)
            this.menu.addMenuItem(this._history[index]);
    },

    _updateHistoryItem: function(index, element) {
        let displayStr = element.replace(/\n/g, ' ');
        let altDisplayStr = _("delete: %s").format(displayStr);
        this._history[index].label.set_text (displayStr);
        this._history[index].actor.show();
    },

    _hideHistory: function(startIndex) {
        for (let index = startIndex || 0; index < this._history.length; ++index)
            this._history[index].actor.hide();
    },

    _onStateChanged: function (state) {
        this._client.on_extension_state_changed(state);
    }
});

let _indicator;

function init(extension) {
    Gettext.bindtextdomain('gpaste', extension.metadata.localedir);
}

function enable() {
    _indicator = new GPasteIndicator();
    _indicator._onStateChanged (true);
    Main.panel.addToStatusArea('gpaste', _indicator);
}

function disable() {
    _indicator._onStateChanged (false);
    _indicator.destroy();
}

<|endoftext|>