<commit_before>import PartyBot from 'partybot-http-client';
import React, { PropTypes, Component } from 'react';
import cssModules from 'react-css-modules';
import styles from './index.module.scss';
import Heading from 'grommet/components/Heading';
import Box from 'grommet/components/Box';
import Footer from 'grommet/components/Footer';
import Button from 'grommet/components/Button';
import Form from 'grommet/components/Form';
import FormField from 'grommet/components/FormField';
import FormFields from 'grommet/components/FormFields';
import NumberInput from 'grommet/components/NumberInput';
import CloseIcon from 'grommet/components/icons/base/Close';
import Dropzone from 'react-dropzone';
import Layer from 'grommet/components/Layer';
import Header from 'grommet/components/Header';
import Section from 'grommet/components/Section';
import Paragraph from 'grommet/components/Paragraph';
import Select from 'react-select';
import request from 'superagent';
import { CLOUDINARY_UPLOAD_PRESET, CLOUDINARY_NAME, CLOUDINARY_KEY, CLOUDINARY_SECRET, CLOUDINARY_UPLOAD_URL } from '../../constants';

class ManageTableTypesPage extends Component {
  constructor(props) {
    super(props);
    this.handleMobile = this.handleMobile.bind(this);
    this.closeSetup = this.closeSetup.bind(this);
    this.onDrop = this.onDrop.bind(this);
    this.onRemoveImage = this.onRemoveImage.bind(this);
    this.onVenueAdd = this.onVenueAdd.bind(this);
    this.setName = this.setName.bind(this);
    this.submitCreate = this.submitCreate.bind(this);
    this.submitSave = this.submitSave.bind(this);
    this.submitDelete = this.submitDelete.bind(this);
    this.state = {
      organisationId: '5800471acb97300011c68cf7',
      no_of_pax: 0,
      isMobile: false,
      image: null,
      prevImage: null,
      isNewImage: false,
      tableTypeId: props.params.table_type_id || null,
      confirm: false,
      name: '',
      tags: 'tabletypes',
      venues: [],
      selectedVenues: [],
    };
  }

  componentDidMount() {
    if (typeof window !== 'undefined') {
      window.addEventListener('resize', this.handleMobile);
    }

    let options = {
      organisationId: this.state.organisationId,
    };
    this.getVenues(options);

    if(this.state.tableTypeId) {
      let ttOptions = {
        organisationId: this.state.organisationId,
        tableTypeId: this.state.tableTypeId
      };
      this.getTableType(ttOptions);
    }

  }
  componentWillUnmount() {
    if (typeof window !== 'undefined') {
      window.removeEventListener('resize', this.handleMobile);
    }
  }
  handleMobile() {
    const isMobile = window.innerWidth <= 768;
    this.setState({
      isMobile,
    });
  }

  onVenueAdd(selectedVenues) {
    this.setState({ selectedVenues });
  }

  closeSetup(){
    this.setState({
     confirm: false
   });
    this.context.router.push('/table-types');
  }

  setName(event) {
    this.setState({name: event.target.value});
  }

  setNoOfPax = (event) => {
    this.setState({no_of_pax: event.target.value});
  };
  onDrop(file) {
    this.setState({
       image: file[0],
       isNewImage: true,
     });
  }
  onRemoveImage() {
    this.setState({
      image: null,
      isNewImage: false,
    });
  }

  handleImageUpload(file, callback) {
    if(this.state.isNewImage) {
      let options = {
        url: CLOUDINARY_UPLOAD_URL,
        formData: {
          file: file
        }
      };
      let upload = request.post(CLOUDINARY_UPLOAD_URL)
      .field('upload_preset', CLOUDINARY_UPLOAD_PRESET)
      .field('file', file);

      upload.end((err, response) => {
        if (err) {
          console.error(err);
        }

        if (response.body.secure_url !== '') {
          callback(null, response.body.secure_url)
        } else {
          callback(err, '');
        }
      });
    } else {
      callback(null, null);
    }
  }

  submitDelete (event) {
    event.preventDefault();
    let params = _.pick(this.state, ['organisationId', 'tableTypeId']);
    PartyBot.tableTypes.deleteTableType(params, (error, response, body) => {
      if(!error && response.statusCode == 200) {
        this.setState({
          confirm: true
        });
      } else {

      }
    });
  }

  submitSave(event) {
    event.preventDefault();
    let venuesArr = this.state.selectedVenues.map(function(value, index) {
      return value.value;
    });
    this.handleImageUpload(this.state.image, (err, imageLink) => {
      if (err) {
        console.log(err);
      } else {
        let updateParams = {
          name: this.state.name,
          organisationId: this.state.organisationId,
          tableTypeId: this.state.tableTypeId,
          no_of_pax: this.state.no_of_pax,
          venue_id: venuesArr,
          image: imageLink || this.state.prevImage.preview || null
        };
        PartyBot.tableTypes.update(updateParams, (err, response, body) => {

          if(response.statusCode == 200) {
            this.setState({
              confirm: true
            });
          }
        });
      }
    });
  }

  submitCreate(event) {
    event.preventDefault();
    let venuesArr = this.state.selectedVenues.map(function(value, index) {
      return value.value;
    });
    this.handleImageUpload(this.state.image, (err, imageLink) => {
      if (err) {
        console.log(err);
      } else {
        let objState = this.state;
        let createParams = {
          organisationId: this.state.organisationId,
          venue_id: venuesArr,
          name: this.state.name,
          no_of_pax: this.state.no_of_pax,
          image: imageLink
        };
        PartyBot.tableTypes.create(createParams, (err, response, body) => {
          if(response.statusCode == 200) {
            this.setState({
              confirm: true
            });
          }
        });
      }
    });
  }

  getVenues(options) {
    PartyBot.venues.getAllInOrganisation(options, (errors, response, body) => {
      if(response.statusCode == 200) {
        let arr = [];
        body.map(function(value, index) {
          arr.push({value: value._id, label: value.name});
        });
        this.setState({venues: arr});
      }
    });
  }

  getTableType(options) {
    return PartyBot.tableTypes.getTableTypesInOrganisation(options, (errors, response, body) => {
      if(response.statusCode == 200) {
        body._venues.map((value, index) => {
          this.setState({
            selectedVenues: this.state.selectedVenues.concat({
              label: value.name,
              value: value._id
            })
          });
        });
        this.setState({
          image: {
            preview: body.image
          },
          prevImage: {
            preview: body.image
          },
          venueId: body.venueId,
          tableTypeId: body._id,
          name: body.name,
          no_of_pax: body.no_of_pax
        });
      }
    });
  };

  render() {
    const {
      router,
    } = this.context;
    const {
      isMobile,
    } = this.state;
    const {
      files,
      variants,
    } = this.state;
    return (
      <Box size={{ width: 'large' }}>

        <link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css" />
        {this.state.confirm !== false ?
        <Layer align="center">

            Table Type successfully created.

            <Button label="Close" onClick={this.closeSetup} plain={true} icon={<CloseIcon />}/>

        </Layer>
        : null
        }
      <Box size={{ width: 'large' }}>
        {this.state.tableTypeId !== null ?
          <Heading align="center">
            Edit Table Type
          </Heading>
          :
          <Heading align="center">
            Add Table Type
          </Heading>
        }
      </Box>
			<Box size={{ width: 'large' }} direction="row" justify="center" align="center" wrap={true} margin="small">
				<Form>
				<FormFields>
					<fieldset>
  	        <Box separator="all">
              <FormField label="Venue" htmlFor="promoterVenue" />
              <Select
                name="promoterVenue"
                options={this.state.venues}
                value={this.state.selectedVenues}
                onChange={this.onVenueAdd}
                multi={true}
                />
         		</Box>
					  <FormField label="Name" htmlFor="tableTypeName">
					    <input id="tableTypeName" type="text" onChange={this.setName} value={this.state.name}/>
					  </FormField>
					  <FormField label="No. of Pax" htmlFor="tablePax">
					    <NumberInput id="tablePax" min={0} max={99} onChange={this.setNoOfPax} value={this.state.no_of_pax}/>
					  </FormField>
            <FormField label="Image">
            {this.state.image ?
              <Box size={{ width: 'large' }} align="center" justify="center">

                <Box size={{ width: 'large' }}>
                  <Button label="Cancel" onClick={this.onRemoveImage.bind(this)} plain={true} icon={<CloseIcon />}/>
                </Box>
              </Box> :
              <Box align="center" justify="center" size={{ width: 'large' }}>
                <Dropzone multiple={false} ref={(node) => { this.dropzone = node; }} onDrop={this.onDrop} accept='image/*'>
                  Drop image here or click to select image to upload.
                </Dropzone>
              </Box>
            }
            </FormField>
          </fieldset>
        </FormFields>

        {
          this.state.tableTypeId !== null ?
          <Heading align="center">
            <Button label="Save Changes" primary={true} onClick={this.submitSave} />
            <Button label="Delete" primary={true} onClick={this.submitDelete} />
          </Heading>
          :
          <Heading align="center">
            <Button label="Create Table Type" primary={true} onClick={this.submitCreate} />
          </Heading>
        }

      </Form>
    </Box>

  </Box>
  );
  }
}

ManageTableTypesPage.contextTypes = {
  router: PropTypes.object.isRequired,
};

export default cssModules(ManageTableTypesPage, styles);
<commit_msg>TEST: New Add Table type UI<commit_after>import PartyBot from 'partybot-http-client';
import React, { PropTypes, Component } from 'react';
import cssModules from 'react-css-modules';
import styles from './index.module.scss';
import Heading from 'grommet/components/Heading';
import Box from 'grommet/components/Box';
import Footer from 'grommet/components/Footer';
import Button from 'grommet/components/Button';
import Form from 'grommet/components/Form';
import FormField from 'grommet/components/FormField';
import FormFields from 'grommet/components/FormFields';
import NumberInput from 'grommet/components/NumberInput';
import CloseIcon from 'grommet/components/icons/base/Close';
import Dropzone from 'react-dropzone';
import Layer from 'grommet/components/Layer';
import Header from 'grommet/components/Header';
import Section from 'grommet/components/Section';
import Paragraph from 'grommet/components/Paragraph';
import Select from 'react-select';
import request from 'superagent';
import { CLOUDINARY_UPLOAD_PRESET, CLOUDINARY_NAME, CLOUDINARY_KEY, CLOUDINARY_SECRET, CLOUDINARY_UPLOAD_URL } from '../../constants';

class ManageTableTypesPage extends Component {
  constructor(props) {
    super(props);
    this.handleMobile = this.handleMobile.bind(this);
    this.state = {
      organisationId: '5800471acb97300011c68cf7',
      no_of_pax: 0,
      isMobile: false,
      isBusy: 0,
      image: null,
      prevImage: null,
      isNewImage: false,
      tableTypeId: props.params.table_type_id || null,
      confirm: false,
      name: '',
      tags: 'tabletypes',
      venues: [],
      events: [],
      selectedVenue: [],
      selectedEvents: [],
      eventVars: []
    };
  }

  componentDidMount() {
    if (typeof window !== 'undefined') {
      window.addEventListener('resize', this.handleMobile);
    }

    let options = {
      organisationId: this.state.organisationId,
    };
    this.getVenues(options);

    if(this.state.tableTypeId) {
      let ttOptions = {
        organisationId: this.state.organisationId,
        tableTypeId: this.state.tableTypeId
      };
      this.getTableType(ttOptions);
    }

  }
  componentWillUnmount() {
    if (typeof window !== 'undefined') {
      window.removeEventListener('resize', this.handleMobile);
    }
  }
  handleMobile = () => {
    const isMobile = window.innerWidth <= 768;
    this.setState({
      isMobile,
    });
  }

  onVenueAdd = (selectedVenue) => {
    this.setState({ selectedVenue: selectedVenue.value });
    let params = {
      organisationId: this.state.organisationId,
      venue_id: selectedVenue.value
    };
    this.getEvents(params)
  }

  onEventAdd = (selectedEvents) => {
    this.setState({ selectedEvents });
  }

  closeSetup = () => {
    this.setState({
     confirm: false
   });
    this.context.router.push('/table-types');
  }

  setName = (event) => {
    this.setState({name: event.target.value});
  }

  setNoOfPax = (event) => {
    this.setState({no_of_pax: event.target.value});
  };

  addEvent = () => {
    this.setState({
      eventVars: this.state.eventVars.concat({
        _venue_id: null,
        description: "Some Description",
        image: null
      })
    });
    console.log(this.state.eventVars);
  }

  removeEvent = () => {

  }

  onDrop = (file) => {
    this.setState({
       image: file[0],
       isNewImage: true,
     });
  }
  onRemoveImage = () => {
    this.setState({
      image: null,
      isNewImage: false,
    });
  }

  handleImageUpload = (file, callback) => {
    if(this.state.isNewImage) {
      let options = {
        url: CLOUDINARY_UPLOAD_URL,
        formData: {
          file: file
        }
      };
      let upload = request.post(CLOUDINARY_UPLOAD_URL)
      .field('upload_preset', CLOUDINARY_UPLOAD_PRESET)
      .field('file', file);

      upload.end((err, response) => {
        if (err) {
          console.error(err);
        }

        if (response.body.secure_url !== '') {
          callback(null, response.body.secure_url)
        } else {
          callback(err, '');
        }
      });
    } else {
      callback(null, null);
    }
  }

  submitDelete = (event) => {
    event.preventDefault();
    let params = _.pick(this.state, ['organisationId', 'tableTypeId']);
    PartyBot.tableTypes.deleteTableType(params, (error, response, body) => {
      if(!error && response.statusCode == 200) {
        this.setState({
          confirm: true
        });
      } else {

      }
    });
  }

  submitSave = (event) => {
    event.preventDefault();
    let venuesArr = this.state.selectedVenue.map(function(value, index) {
      return value.value;
    });
    this.handleImageUpload(this.state.image, (err, imageLink) => {
      if (err) {
        console.log(err);
      } else {
        let updateParams = {
          name: this.state.name,
          organisationId: this.state.organisationId,
          tableTypeId: this.state.tableTypeId,
          no_of_pax: this.state.no_of_pax,
          venue_id: venuesArr,
          image: imageLink || this.state.prevImage.preview || null
        };
        PartyBot.tableTypes.update(updateParams, (err, response, body) => {

          if(response.statusCode == 200) {
            this.setState({
              confirm: true
            });
          }
        });
      }
    });
  }

  submitCreate = (event) => {
    event.preventDefault();
    console.log(this.state);
    // this.handleImageUpload(this.state.image, (err, imageLink) => {
    //   if (err) {
    //     console.log(err);
    //   } else {
    //     let objState = this.state;
    //     let createParams = {
    //       organisationId: this.state.organisationId,
    //       venue_id: venuesArr,
    //       name: this.state.name,
    //       no_of_pax: this.state.no_of_pax,
    //       image: imageLink
    //     };
    //     PartyBot.tableTypes.create(createParams, (err, response, body) => {
    //       if(response.statusCode == 200) {
    //         this.setState({
    //           confirm: true
    //         });
    //       }
    //     });
    //   }
    // });
  }

  getVenues = (options) => {
    PartyBot.venues.getAllInOrganisation(options, (errors, response, body) => {
      if(response.statusCode == 200) {
        let arr = [];
        body.map(function(value, index) {
          arr.push({value: value._id, label: value.name});
        });
        this.setState({venues: arr});
      }
    });
  }

  getEvents = (options) => {
    PartyBot.events.getEventsInOrganisation(options, (err, response, body) => {
      console.log(body);
      if(!err && response.statusCode == 200) {
        if(body.length > 0) {
          this.setState({eventId: body[0]._id});
        }
        let arr = [];
        body.map(function(value, index) {
          arr.push({value: value._id, label: value.name});
        });
        this.setState({events: arr});
      }
    });
  }

  getTableType = (options) => {
    return PartyBot.tableTypes.getTableTypesInOrganisation(options, (errors, response, body) => {
      if(response.statusCode == 200) {
        body._venues.map((value, index) => {
          this.setState({
            selectedVenue: this.state.selectedVenue.concat({
              label: value.name,
              value: value._id
            })
          });
        });
        this.setState({
          image: {
            preview: body.image
          },
          prevImage: {
            preview: body.image
          },
          venueId: body.venueId,
          tableTypeId: body._id,
          name: body.name,
          no_of_pax: body.no_of_pax
        });
      }
    });
  };
  renderEventVars = () => {
    return this.state.eventVars.map((value, index) => {
    return (
      <Box key={index} separator="all" pad={{"vertical": "medium"}}>
        <FormField label="Event" htmlFor="event" />
        <Select
          name="events"
          options={this.state.events}
          value={this.state.selectedEvents}
          onChange={this.onEventAdd}
          multi={true}
          />
        <FormField label="Image">
        {this.state.image ?
          <Box size={{ width: 'large' }} align="center" justify="center">

            <Box size={{ width: 'large' }}>
              <Button label="Cancel" onClick={this.onRemoveImage.bind(this)} plain={true} icon={<CloseIcon />}/>
            </Box>
          </Box> :
          <Box align="center" justify="center" size={{ width: 'large' }}>
            <Dropzone multiple={false} ref={(node) => { this.dropzone = node; }} onDrop={this.onDrop} accept='image/*'>
              Drop image here or click to select image to upload.
            </Dropzone>
          </Box>
        }
        </FormField>
      </Box>)
    });
  }
  render() {
    const {
      router,
    } = this.context;
    const {
      isMobile,
    } = this.state;
    const {
      files,
      variants,
    } = this.state;
    return (
      <Box size={{ width: 'large' }}>

        <link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css" />
        {this.state.confirm !== false ?
        <Layer align="center">

            Table Type successfully created.

            <Button label="Close" onClick={this.closeSetup} plain={true} icon={<CloseIcon />}/>

        </Layer>
        : null
        }
      <Box size={{ width: 'large' }}>
        {this.state.tableTypeId !== null ?
          <Heading align="center">
            Edit Table Type
          </Heading>
          :
          <Heading align="center">
            Add Table Type
          </Heading>
        }
      </Box>
			<Box size={{ width: 'large' }} direction="row" justify="center" align="center" wrap={true} margin="small">
				<Form>
				<FormFields>
					<fieldset>
            <Box separator="all">
              <FormField label="Venue" htmlFor="promoterVenue" />
              <Select
                name="promoterVenue"
                options={this.state.venues}
                value={this.state.selectedVenue}
                onChange={this.onVenueAdd}
                />
              <FormField label="Name" htmlFor="tableTypeName">
                <input id="tableTypeName" type="text" onChange={this.setName} value={this.state.name}/>
              </FormField>
            </Box>
            {this.renderEventVars()}
            <Box size={{width: 'medium'}}>
              <Button label="Add Event" primary={true} onClick={this.addEvent} />
            </Box>
          </fieldset>
        </FormFields>

        {
          this.state.tableTypeId !== null ?
          <Heading align="center">
            <Button label="Save Changes" primary={true} onClick={this.submitSave} />
            <Button label="Delete" primary={true} onClick={this.submitDelete} />
          </Heading>
          :
          <Heading align="center">
            <Button label="Create Table Type" primary={true} onClick={this.submitCreate} />
          </Heading>
        }

      </Form>
    </Box>

  </Box>
  );
  }
}

ManageTableTypesPage.contextTypes = {
  router: PropTypes.object.isRequired,
};

export default cssModules(ManageTableTypesPage, styles);
<|endoftext|>


<commit_before>/*
 * DealPort
 * Copyright (c) 2014  DealPort B.V.
 *
 * This file is part of DealPort
 *
 * DealPort is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * DealPort 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 Affero General Public License
 * along with DealPort.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, the following supplemental terms apply, based on section 7 of
 * the GNU Affero General Public License (version 3):
 * a) Preservation of all legal notices and author attributions
 */

'use strict';

var P = require('bluebird');

var Model = require('./Model');

/**
 *
 * Looks like in mongo:
 *
 * {
 *  "_id" : "my name (displayed in URLs)",
 *  "company: "company id"
 *  "user: ObjectId("user id")
 * }
 *
 * @param modelIndex
 * @constructor
 */
function NamedEntityModel(modelIndex)
{
        Model.call(this, modelIndex);
}

module.exports = NamedEntityModel;
require('inherits')(NamedEntityModel, Model);

NamedEntityModel.prototype.cleanupName = function(name)
{
        if (!name)
        {
                return '';
        }

        name = name.toString();
        name = name.replace(/[\x00-\x1F]+/g, ''); // ascii control chars
        name = name.trim();

        // replace spaces with dashes
        name = name.replace(/\s+/g, '-');
        return name;
};

NamedEntityModel.prototype.createByGuessingId = function(named)
{
        var livedb = this.modelIndex.livedb;

        named._id = null;

        return P.using(this.modelIndex.acquire(), function(db)
        {
                var p;
                var namePromise;
                var existingNamedIdPromise;
                var companyVersionPromise;
                var id;
                var removeObj;

                if (named.company)
                {
                        id = named.company;
                        removeObj = {company: named.company};
                        p = db.company.findOneAsync({_id: id}, {name: 1, namedEntityId: 1, _v: 1});
                        namePromise = p.get('name');
                        existingNamedIdPromise = p.get('namedEntityId');
                        companyVersionPromise = p.get('_v');
                }
                else if (named.user)
                {
                        id = named.user;
                        removeObj = {user: named.user};
                        p = db.user.findOneAsync({_id: id}, {displayName: 1, namedEntityId: 1});
                        namePromise = p.get('displayName');
                        existingNamedIdPromise = p.get('namedEntityId');
                }
                else
                {
                        throw Error('Invalid argument');
                }

                namePromise = namePromise.then(this.cleanupName);

                return P.join(namePromise, existingNamedIdPromise, function(name, previousNamedId)
                {
                        if (!name)
                        {
                                return [];
                        }

                        var attempts = [];
                        for (var i = 1; i <= 25; ++i)
                        {
                                var nameAttempt = name + (i > 1 ? ' ' + i : '');

                                if (previousNamedId === nameAttempt)
                                {
                                        // we already have this name, use the existing namedEntity by rejecting,
                                        // skipping all the other database stuff
                                        named._id = previousNamedId;
                                        // start with $ to discourage saving this back into mongo...
                                        named.$reuseExistingNamedEntityBailout = true;
                                        return P.reject(named);
                                }

                                if (/^[0-9a-zA-Z]{24}$/.test(nameAttempt))
                                {
                                        // ObjectIDs are reserved
                                        nameAttempt += 'x';
                                }

                                attempts.push(P.join(
                                        nameAttempt,
                                        db.namedEntity.findOneAsync({_id: nameAttempt}, {dummy: 1, _id: 0})
                                ));
                        }

                        return P.all(attempts);
                })
                .then(function(attempts)
                {
                        for (var i = 0; i < attempts.length; ++i)
                        {
                                var attempt = attempts[i];
                                if (!attempt[1])
                                {
                                        return attempt[0];
                                }
                        }

                        // give up
                        return null;
                })
                .then(function(unusedName)
                {
                        if (unusedName)
                        {
                                named._id = unusedName;
                        }
                        else
                        {
                                // use the OID of the entity
                                named._id = id.toString();
                        }

                        // avoid unique index errors
                        var bulk = db.namedEntity._native.initializeOrderedBulkOp();
                        bulk.executeAsync = P.promisify(bulk.execute);
                        bulk.find(removeObj).removeOne();
                        if (unusedName)
                        {
                                bulk.insert(named);
                        } // else: do not insert ObjectId's in namedEntity

                        return bulk.executeAsync()
                        .catch(function(err)
                        {
                                console.error('Error in NamedEntityModel.prototype.createByGuessingId bulk operation', err, err.stack);
                                // use the OID of the entity as fallback
                                named._id = id.toString();
                        })
                        .return(named);
                })
                .then(function(named)
                {
                        // if creating the new named entity was successful,
                        // update the entity too

                        if (named.company)
                        {
                                return livedb.submitAsync('company', named.company, {
                                        op: [
                                                {
                                                        p: ['namedEntityId'],
                                                        od: existingNamedIdPromise.value(),
                                                        oi: named._id
                                                }
                                        ],
                                        v : companyVersionPromise.value()
                                });
                        }
                        else if (named.user)
                        {
                                return db.user.updateAsync(
                                        {_id: named.user},
                                        { $set: {namedEntityId: named._id} }
                                );
                        }

                        return null;
                })
                .catch(function(namedOrError)
                {
                        if (namedOrError &&
                            namedOrError.$reuseExistingNamedEntityBailout)
                        {
                                return P.resolve(namedOrError);
                        }

                        return P.reject(namedOrError);
                });
        }.bind(this))
        .return(named);
};
<commit_msg>Use dashes when adding numbers to a named entity too<commit_after>/*
 * DealPort
 * Copyright (c) 2014  DealPort B.V.
 *
 * This file is part of DealPort
 *
 * DealPort is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * DealPort 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 Affero General Public License
 * along with DealPort.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, the following supplemental terms apply, based on section 7 of
 * the GNU Affero General Public License (version 3):
 * a) Preservation of all legal notices and author attributions
 */

'use strict';

var P = require('bluebird');

var Model = require('./Model');

/**
 *
 * Looks like in mongo:
 *
 * {
 *  "_id" : "my name (displayed in URLs)",
 *  "company: "company id"
 *  "user: ObjectId("user id")
 * }
 *
 * @param modelIndex
 * @constructor
 */
function NamedEntityModel(modelIndex)
{
        Model.call(this, modelIndex);
}

module.exports = NamedEntityModel;
require('inherits')(NamedEntityModel, Model);

NamedEntityModel.prototype.cleanupName = function(name)
{
        if (!name)
        {
                return '';
        }

        name = name.toString();
        name = name.replace(/[\x00-\x1F]+/g, ''); // ascii control chars
        name = name.trim();

        // replace spaces with dashes
        name = name.replace(/\s+/g, '-');
        return name;
};

NamedEntityModel.prototype.createByGuessingId = function(named)
{
        var livedb = this.modelIndex.livedb;

        named._id = null;

        return P.using(this.modelIndex.acquire(), function(db)
        {
                var p;
                var namePromise;
                var existingNamedIdPromise;
                var companyVersionPromise;
                var id;
                var removeObj;

                if (named.company)
                {
                        id = named.company;
                        removeObj = {company: named.company};
                        p = db.company.findOneAsync({_id: id}, {name: 1, namedEntityId: 1, _v: 1});
                        namePromise = p.get('name');
                        existingNamedIdPromise = p.get('namedEntityId');
                        companyVersionPromise = p.get('_v');
                }
                else if (named.user)
                {
                        id = named.user;
                        removeObj = {user: named.user};
                        p = db.user.findOneAsync({_id: id}, {displayName: 1, namedEntityId: 1});
                        namePromise = p.get('displayName');
                        existingNamedIdPromise = p.get('namedEntityId');
                }
                else
                {
                        throw Error('Invalid argument');
                }

                namePromise = namePromise.then(this.cleanupName);

                return P.join(namePromise, existingNamedIdPromise, function(name, previousNamedId)
                {
                        if (!name)
                        {
                                return [];
                        }

                        var attempts = [];
                        for (var i = 1; i <= 25; ++i)
                        {
                                var nameAttempt = name + (i > 1 ? '-' + i : '');

                                if (previousNamedId === nameAttempt)
                                {
                                        // we already have this name, use the existing namedEntity by rejecting,
                                        // skipping all the other database stuff
                                        named._id = previousNamedId;
                                        // start with $ to discourage saving this back into mongo...
                                        named.$reuseExistingNamedEntityBailout = true;
                                        return P.reject(named);
                                }

                                if (/^[0-9a-zA-Z]{24}$/.test(nameAttempt))
                                {
                                        // ObjectIDs are reserved
                                        nameAttempt += 'x';
                                }

                                attempts.push(P.join(
                                        nameAttempt,
                                        db.namedEntity.findOneAsync({_id: nameAttempt}, {dummy: 1, _id: 0})
                                ));
                        }

                        return P.all(attempts);
                })
                .then(function(attempts)
                {
                        for (var i = 0; i < attempts.length; ++i)
                        {
                                var attempt = attempts[i];
                                if (!attempt[1])
                                {
                                        return attempt[0];
                                }
                        }

                        // give up
                        return null;
                })
                .then(function(unusedName)
                {
                        if (unusedName)
                        {
                                named._id = unusedName;
                        }
                        else
                        {
                                // use the OID of the entity
                                named._id = id.toString();
                        }

                        // avoid unique index errors
                        var bulk = db.namedEntity._native.initializeOrderedBulkOp();
                        bulk.executeAsync = P.promisify(bulk.execute);
                        bulk.find(removeObj).removeOne();
                        if (unusedName)
                        {
                                bulk.insert(named);
                        } // else: do not insert ObjectId's in namedEntity

                        return bulk.executeAsync()
                        .catch(function(err)
                        {
                                console.error('Error in NamedEntityModel.prototype.createByGuessingId bulk operation', err, err.stack);
                                // use the OID of the entity as fallback
                                named._id = id.toString();
                        })
                        .return(named);
                })
                .then(function(named)
                {
                        // if creating the new named entity was successful,
                        // update the entity too

                        if (named.company)
                        {
                                return livedb.submitAsync('company', named.company, {
                                        op: [
                                                {
                                                        p: ['namedEntityId'],
                                                        od: existingNamedIdPromise.value(),
                                                        oi: named._id
                                                }
                                        ],
                                        v : companyVersionPromise.value()
                                });
                        }
                        else if (named.user)
                        {
                                return db.user.updateAsync(
                                        {_id: named.user},
                                        { $set: {namedEntityId: named._id} }
                                );
                        }

                        return null;
                })
                .catch(function(namedOrError)
                {
                        if (namedOrError &&
                            namedOrError.$reuseExistingNamedEntityBailout)
                        {
                                return P.resolve(namedOrError);
                        }

                        return P.reject(namedOrError);
                });
        }.bind(this))
        .return(named);
};
<|endoftext|>


<commit_before>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
var Minify = {};
console.log('minify.js loaded...');

/* функция сжимает js-скрипты
 * и сохраняет их с именем .min.js
 */

var fs = require('fs');
var path=require('path');
var crypto = require('crypto');

var Hashes;

var MinFolder='min/';
/* function clear MinFolder
 * if we could not create
 * directory and it is
 * not exist
 */
var folderExist = function(pError, pStat){
    "use strict";
    /*file found and it's directory */
    if(!pError && pStat.isDirectory())
        console.log('folder exist: ' + MinFolder);
    else MinFolder='/';
};

/*
 * function says thet folder created
 * if everything is OK, or
 * moves to folderExist function
 */
var makeFolder = function(pError){
    "use strict";
    /*folder created successfully*/
    if(!pError)
        console.log('folder created: min');
    else fs.stat(MinFolder,folderExist);
};

/* Trying to create folder min
 * where woud be minifyed versions
 * of files 511(10)=777(8)
 * rwxrwxrwx
 */
fs.mkdir(MinFolder,511,makeFolder);

exports.MinFolder = MinFolder;
exports.Cache    = {};

/*********************************/
/* сжимаем код через uglify-js */
Minify._uglifyJS= function(pDdata){

    /* подключаем модуль uglify-js
     * если его нет - дальнейшая
     * работа функции не имеет смысла
     */
    var jsp;
    var pro;
    try{
        jsp = require("uglify-js").parser;
        pro = require("uglify-js").uglify;
    }catch(error){
        console.log('can\'n load uglify-js\n'                  +
            'to use js-minification you need to install uglify-js\n'    +
                'npm install uglify-js\n'                               +
                'https://github.com/mishoo/UglifyJS');
        return false;
    }

    var orig_code = pDdata.toString();
    var ast = jsp.parse(orig_code); // parse code and get the initial AST
    ast = pro.ast_mangle(ast); // get a new AST with mangled names
    ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    var result_code = pro.gen_code(ast); // compressed code here
    return result_code;
};

/* сжимаем код через clean-css */
Minify._cleanCSS=function(pData){
    'use strict';
     /* connecting cleanCSS,
      * if we can't find it -
      * return false
      */
     var cleanCSS;
     try{
        cleanCSS = require('clean-css');
    }catch(error){
        console.log('can\'n load clean-css \n'                          +
            'to use css-minification you need to install clean-css \n'  +
                'npm install clean-css\n'                               +
                'https://github.com/GoalSmashers/clean-css');
        return false;
    }
        /* Сохраняем весь стиль в одну переменную*/
    return cleanCSS.process(pData);
};

/* сжимаем код через htmlMinify */
Minify.htmlMinify=function(pData){
    /* Сохраняем весь стиль в одну переменную*/

     /* connecting cleanCSS,
      * if we can't find it -
      * return false
      */
     var htmlMinifier;
     try{
        htmlMinifier = require('html-minifier');
    }catch(error){
        console.log('can\'n load html-minifier \n'                 +
            'to use html-minification you need to install html-minifier\n'  +
                'npm install html-minifier\n'                               +
                'https://github.com/kangax/html-minifier');
        return false;
    }

    var lOptions={
        removeComments:                 true,
        removeCommentsFromCDATA:        true,
        removeCDATASectionsFromCDATA:   true,
        collapseWhitespace:             true,
        collapseBooleanAttributes:      true,
        removeAttributeQuotes:          true,
        removeRedundantAttributes:      true,
        useShortDoctype:                true,
        removeEmptyAttributes:          true,
        /* оставляем, поскольку у нас
         * в элемент fm генерируеться
         * таблица файлов
         */
        removeEmptyElements:            false,
        removeOptionalTags:             true,
        removeScriptTypeAttributes:     true,
        removeStyleLinkTypeAttributes:  true
    };

    return htmlMinifier.minify(pData,lOptions);
};
/*********************************/

/*
 * Функция ищет в имени файла расширение
 * и если находит возвращает true
 * @pName - получает имя файла
 * @pExt - расширение
 */
Minify._checkExtension=function(pName,pExt)
{
    /* если длина имени больше
     * длинны расширения -
     * имеет смысл продолжать
     */
    if(pName.length>pExt.length){
        var lLength=pName.length;           /* длина имени*/
        var lExtNum=pName.lastIndexOf(pExt);/* последнее вхождение расширения*/
        var lExtSub=lLength-lExtNum;        /* длина расширения*/
        /* если pExt - расширение pName */
        if(lExtSub===pExt.length)
            return true;
        else
            return false;
    }
    else return false;
}

/* function minificate js,css and html files
 * @pFiles_a                - array of js, css and html file names or string, if name
 *                            single, or object if postProcessing neaded
 *                              {'client.js': function(pFinalCode){} }
 *                            or convertion images to base64 neaded
 *                              {'style.css': true}
 *                            or {'style.css':{minimize: true, func: function(){}}
 * @pCache_b                - if true files do not writes on disk, just saves
 *                              in Minify Cache
 */
exports.optimize = function(pFiles_a, pCache_b){
    'use strict';

     /* if passed string, or object
     * putting it to array
     */
    if (typeof pFiles_a === 'string' ||
        !pFiles_a[0])
            pFiles_a=[pFiles_a];

    var lName;

    var lAllCSS;
    var dataReaded_f=function(pFileName, pData){
        /*
         * if postProcessing function exist
         * getting it from pFileName object
         */
        var lMoreProcessing_f;
        if(typeof pFileName === 'object'){
            var lName;
            for(lName in pFileName){
                break;
            }
            lMoreProcessing_f = pFileName[lName];
            pFileName = lName;
        }
        console.log('file ' + pFileName + ' readed');

        if (!isFileChanged(pFileName, pData)) {
            console.log('file: ' + pFileName + ' do not changed...');
            return;
        }

        var final_code;
        var minFileName;

        /* if it's js file - getting optimized version */
        if(Minify._checkExtension(pFileName,'js')){

            final_code=Minify._uglifyJS(pData);
            minFileName=pFileName.replace('.js', '.min.js');

        } else if (Minify._checkExtension(pFileName, 'html')) {

            final_code=Minify.htmlMinify(pData);
            minFileName=pFileName.replace('.html', '.min.html');

        } else if (Minify._checkExtension(pFileName, 'css')) {

            final_code=Minify._cleanCSS(pData);
            lAllCSS+=final_code;
            minFileName=pFileName.replace('.css','.min.css');

            /* in css could be lCSS_o
             * {img: true, moreProcessing: function(){}}
             */
            var lCSS_o = lMoreProcessing_f;
            if (lCSS_o                      &&
                typeof lCSS_o === 'object'  &&
                lCSS_o.img){
                    base64_images(lAllCSS);
                    lMoreProcessing_f = lCSS_o.moreProcessing;
            }else if (typeof lCSS_o ==='boolean' &&
                lCSS_o === true){
                base64_images(lAllCSS);
            }
        } else
            return;

        /* if lMoreProcessing_f seeted up
         * and function associated with
         * current file name exists -
         * run it
         */
        if(lMoreProcessing_f                    &&
            typeof lMoreProcessing_f === "function"){
                final_code = lMoreProcessing_f(final_code);
        }

        minFileName = path.basename(minFileName);

        /* записываем сжатый js-скрипт
         * в кэш если установлен pCache_b
         * или на диск, если не установлен
         */
        if(pCache_b){
            exports.Cache[minFileName] = final_code;
            console.log('file ' + minFileName + ' saved to cache...');
        }
        else{
            /* minimized file will be in min file
             * if it's possible if not -
             * in root
             */
            minFileName = MinFolder + minFileName;

            fs.writeFile(minFileName, final_code, fileWrited(minFileName));
        }
    }
    /* moving thru all elements of js files array */
    for(var i=0; pFiles_a[i]; i++){
        /* if postProcessing function exist
         * getting file name and passet next
         */
        var lPostProcessing_o = pFiles_a[i];
        if(typeof lPostProcessing_o === 'object'){
            for(lName in lPostProcessing_o){
            }
        } else lName = pFiles_a[i];
        console.log('reading file ' + lName + '...');

        /* if it's last file send true */
        fs.readFile(lName,
            fileReaded(pFiles_a[i],
                dataReaded_f,
                (i===pFiles_a.length)?true:false));
    }
    /* saving the name of last readed file for hash saving function */

    return true;
};

/* функция сжимает css-стили
 * и сохраняет их с именем .min.css
 * @pCSSFiles_a           - масив имен css файлов или строка,
 *                          если имя одно
 * @pImgConvertToBase64_b - булевый признак,
 *                          который отвечает за то, что быконвертировать
 *                          картинки в base64 и поместить в выходной css файл
 */
exports.cssStyles=function cssStyles(pCSSFiles_a, pImgConvertToBase64_b){

    if(typeof pCSSFiles_a === "string")
        pCSSFiles_a=[pCSSFiles_a];
    /* Varible contains information
     * about readed css file
     */
    var lCSSFiles_doneCount=0;

    var lAllStyle='';

    var dataReaded_f=function(pFileName, pData) {

        console.log('file ' + pFileName + ' readed');
        var final_code=Minify._cleanCSS(pData);

        lAllStyle+=final_code;

        var minFileName=pFileName.replace('.css','.min.css');

        ++lCSSFiles_doneCount;

        /* if all files writed we
         * save all minimized css
         * to one file all.min.css
         */
        if(pCSSFiles_a.length === lCSSFiles_doneCount){
            /* если включена конвертация картинок в base64
             * вызываем её
             */
            if(pImgConvertToBase64_b)
                base64_images(lAllStyle);
            else
                fs.writeFile(MinFolder + 'all.min.css', lAllStyle, fileWrited(MinFolder + 'all.min.css'));
        }
         /* в другом случае - записываем сжатый css файл*/
        else{
            minFileName = MinFolder + path.basename(minFileName);
            fs.writeFile(minFileName, final_code, fileWrited(minFileName));
        }
    };

   /* moving thru all elements of css files array */
    for(var i=0;pCSSFiles_a[i];i++){
        console.log('reading file ' + pCSSFiles_a[i]+'...');
        fs.readFile(pCSSFiles_a[i],fileReaded(pCSSFiles_a[i],dataReaded_f));
    }

    return true;
};

/* функция переводит картинки в base64 и записывает в css-файл*/
function base64_images(pFileContent_s){
    'use strict';
     var b64img;
     try{
        b64img = require('css-b64-images');
    }catch(error){
        console.log('can\'n load clean-css \n'                 +
            'to use images to base64 convertation you need to install css-base64-images \n'  +
                'npm install -g css-b64-images\n'                               +
                'https://github.com/Filirom1/css-base64-images');
        return false;
    }
    b64img.fromString(pFileContent_s, '.','', function(err, css){
        console.log('images converted to base64 and saved in css file');
        fs.writeFile(MinFolder + 'all.min.css', css, fileWrited(MinFolder + 'all.min.css'));
    });
}

/* Функция создаёт асинхроную версию
 * для чтения файла
 * @pFileName - имя считываемого файла
 */
function fileReaded(pFileName,pCompressFunc){
    "use strict";
    return function(pError,pData){
        /* функция в которую мы попадаем,
         * если данные считались
         *
         * если ошибка - показываем её
         * иначе если переданная функция -
         * функция запускаем её
         */
        if(!pError)
            if (pCompressFunc && typeof pCompressFunc==="function")
                    pCompressFunc(pFileName,pData.toString());
        else console.log(pError);
    };
}

/*
 * Функция вызываеться после записи файла
 * и выводит ошибку или сообщает,
 * что файл успешно записан
 */
function fileWrited(pFileName){
    "use strict";
    return function(error){
        console.log(error?error:('file '+pFileName+' writed...'));
    };
}

/*
 * Function reads hash table of files
 * checks is file changed or not
 * and return result.
 * @pFileName - name of file
 * @pFileData - data of file
 * result: boolean
 */
function isFileChanged(pFileName, pFileData){
        var lReadedHash;

        if(!Hashes)
            try {
                /* try to read file with hashes */
                Hashes = require('hashes.json');
                for(var lFileName in Hashes)
                    /* if founded row with file name
                     * saving hash
                     */
                    if (lFileName === pFileName) {
                        lReadedHash = Hashes[pFileName];
                        break;
                    }
            }catch(pError) {
                Hashes={};
            }
        /* create md5 hash of file data */
        var lFileHash = crypto.createHash('sha1');
        lFileHash.update(pFileData);
        lFileHash = lFileHash.digest('hex');

        console.log(pFileName + ': ' + lFileHash);

        if(lReadedHash &&
            lReadedHash === lFileHash){
                /* file did not change */
                return false;
        }else{
            Hashes[pFileName] = lFileHash;
            console.log(Hashes);

            return true;
        }
}<commit_msg>removed cssStyles function<commit_after>/* Модуль сжатия js-скриптов, css-стилей, html-файлов и
 * конвертации картинок в css-стилях
 * в base64 и помещения их в файл стилей
 */
var Minify = {};
console.log('minify.js loaded...');

/* функция сжимает js-скрипты
 * и сохраняет их с именем .min.js
 */

var fs = require('fs');
var path=require('path');
var crypto = require('crypto');

var Hashes;

var MinFolder='min/';
/* function clear MinFolder
 * if we could not create
 * directory and it is
 * not exist
 */
var folderExist = function(pError, pStat){
    "use strict";
    /*file found and it's directory */
    if(!pError && pStat.isDirectory())
        console.log('folder exist: ' + MinFolder);
    else MinFolder='/';
};

/*
 * function says thet folder created
 * if everything is OK, or
 * moves to folderExist function
 */
var makeFolder = function(pError){
    "use strict";
    /*folder created successfully*/
    if(!pError)
        console.log('folder created: min');
    else fs.stat(MinFolder,folderExist);
};

/* Trying to create folder min
 * where woud be minifyed versions
 * of files 511(10)=777(8)
 * rwxrwxrwx
 */
fs.mkdir(MinFolder,511,makeFolder);

exports.MinFolder = MinFolder;
exports.Cache    = {};

/*********************************/
/* сжимаем код через uglify-js */
Minify._uglifyJS= function(pDdata){

    /* подключаем модуль uglify-js
     * если его нет - дальнейшая
     * работа функции не имеет смысла
     */
    var jsp;
    var pro;
    try{
        jsp = require("uglify-js").parser;
        pro = require("uglify-js").uglify;
    }catch(error){
        console.log('can\'n load uglify-js\n'                  +
            'to use js-minification you need to install uglify-js\n'    +
                'npm install uglify-js\n'                               +
                'https://github.com/mishoo/UglifyJS');
        return false;
    }

    var orig_code = pDdata.toString();
    var ast = jsp.parse(orig_code); // parse code and get the initial AST
    ast = pro.ast_mangle(ast); // get a new AST with mangled names
    ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    var result_code = pro.gen_code(ast); // compressed code here
    return result_code;
};

/* сжимаем код через clean-css */
Minify._cleanCSS=function(pData){
    'use strict';
     /* connecting cleanCSS,
      * if we can't find it -
      * return false
      */
     var cleanCSS;
     try{
        cleanCSS = require('clean-css');
    }catch(error){
        console.log('can\'n load clean-css \n'                          +
            'to use css-minification you need to install clean-css \n'  +
                'npm install clean-css\n'                               +
                'https://github.com/GoalSmashers/clean-css');
        return false;
    }
        /* Сохраняем весь стиль в одну переменную*/
    return cleanCSS.process(pData);
};

/* сжимаем код через htmlMinify */
Minify.htmlMinify=function(pData){
    /* Сохраняем весь стиль в одну переменную*/

     /* connecting cleanCSS,
      * if we can't find it -
      * return false
      */
     var htmlMinifier;
     try{
        htmlMinifier = require('html-minifier');
    }catch(error){
        console.log('can\'n load html-minifier \n'                 +
            'to use html-minification you need to install html-minifier\n'  +
                'npm install html-minifier\n'                               +
                'https://github.com/kangax/html-minifier');
        return false;
    }

    var lOptions={
        removeComments:                 true,
        removeCommentsFromCDATA:        true,
        removeCDATASectionsFromCDATA:   true,
        collapseWhitespace:             true,
        collapseBooleanAttributes:      true,
        removeAttributeQuotes:          true,
        removeRedundantAttributes:      true,
        useShortDoctype:                true,
        removeEmptyAttributes:          true,
        /* оставляем, поскольку у нас
         * в элемент fm генерируеться
         * таблица файлов
         */
        removeEmptyElements:            false,
        removeOptionalTags:             true,
        removeScriptTypeAttributes:     true,
        removeStyleLinkTypeAttributes:  true
    };

    return htmlMinifier.minify(pData,lOptions);
};
/*********************************/

/*
 * Функция ищет в имени файла расширение
 * и если находит возвращает true
 * @pName - получает имя файла
 * @pExt - расширение
 */
Minify._checkExtension=function(pName,pExt)
{
    /* если длина имени больше
     * длинны расширения -
     * имеет смысл продолжать
     */
    if(pName.length>pExt.length){
        var lLength=pName.length;           /* длина имени*/
        var lExtNum=pName.lastIndexOf(pExt);/* последнее вхождение расширения*/
        var lExtSub=lLength-lExtNum;        /* длина расширения*/
        /* если pExt - расширение pName */
        if(lExtSub===pExt.length)
            return true;
        else
            return false;
    }
    else return false;
}

/* function minificate js,css and html files
 * @pFiles_a                - array of js, css and html file names or string, if name
 *                            single, or object if postProcessing neaded
 *                              {'client.js': function(pFinalCode){} }
 *                            or convertion images to base64 neaded
 *                              {'style.css': true}
 *                            or {'style.css':{minimize: true, func: function(){}}
 * @pCache_b                - if true files do not writes on disk, just saves
 *                              in Minify Cache
 */
exports.optimize = function(pFiles_a, pCache_b){
    'use strict';

     /* if passed string, or object
     * putting it to array
     */
    if (typeof pFiles_a === 'string' ||
        !pFiles_a[0])
            pFiles_a=[pFiles_a];

    var lName;

    var lAllCSS;
    var dataReaded_f=function(pFileName, pData, pLastFile_b){
        /*
         * if postProcessing function exist
         * getting it from pFileName object
         */
        var lMoreProcessing_f;
        if(typeof pFileName === 'object'){
            var lName;
            for(lName in pFileName){
                break;
            }
            lMoreProcessing_f = pFileName[lName];
            pFileName = lName;
        }
        console.log('file ' + pFileName + ' readed');

        if (!isFileChanged(pFileName, pData, pLastFile_b)) {
            console.log('file: ' + pFileName + ' do not changed...');
            return;
        }

        var final_code;
        var minFileName;

        /* if it's js file - getting optimized version */
        if(Minify._checkExtension(pFileName,'js')){

            final_code=Minify._uglifyJS(pData);
            minFileName=pFileName.replace('.js', '.min.js');

        } else if (Minify._checkExtension(pFileName, 'html')) {

            final_code=Minify.htmlMinify(pData);
            minFileName=pFileName.replace('.html', '.min.html');

        } else if (Minify._checkExtension(pFileName, 'css')) {

            final_code=Minify._cleanCSS(pData);
            lAllCSS+=final_code;
            minFileName=pFileName.replace('.css','.min.css');

            /* in css could be lCSS_o
             * {img: true, moreProcessing: function(){}}
             */
            var lCSS_o = lMoreProcessing_f;
            if (lCSS_o                      &&
                typeof lCSS_o === 'object'  &&
                lCSS_o.img){
                    base64_images(lAllCSS);
                    lMoreProcessing_f = lCSS_o.moreProcessing;
            }else if (typeof lCSS_o ==='boolean' &&
                lCSS_o === true){
                base64_images(lAllCSS);
            }
        } else
            return;

        /* if lMoreProcessing_f seeted up
         * and function associated with
         * current file name exists -
         * run it
         */
        if(lMoreProcessing_f                    &&
            typeof lMoreProcessing_f === "function"){
                final_code = lMoreProcessing_f(final_code);
        }

        minFileName = path.basename(minFileName);

        /* записываем сжатый js-скрипт
         * в кэш если установлен pCache_b
         * или на диск, если не установлен
         */
        if(pCache_b){
            exports.Cache[minFileName] = final_code;
            console.log('file ' + minFileName + ' saved to cache...');
        }
        else{
            /* minimized file will be in min file
             * if it's possible if not -
             * in root
             */
            minFileName = MinFolder + minFileName;

            fs.writeFile(minFileName, final_code, fileWrited(minFileName));
        }
    }
    /* moving thru all elements of js files array */
    for(var i=0; pFiles_a[i]; i++){
        /* if postProcessing function exist
         * getting file name and passet next
         */
        var lPostProcessing_o = pFiles_a[i];
        if(typeof lPostProcessing_o === 'object'){
            for(lName in lPostProcessing_o){
            }
        } else lName = pFiles_a[i];
        console.log('reading file ' + lName + '...');

        /* if it's last file send true */
        fs.readFile(lName,
            fileReaded(pFiles_a[i],
                dataReaded_f,
                (i===pFiles_a.length)?true:false));
    }
    /* saving the name of last readed file for hash saving function */

    return true;
};

/* функция переводит картинки в base64 и записывает в css-файл*/
function base64_images(pFileContent_s){
    'use strict';
     var b64img;
     try{
        b64img = require('css-b64-images');
    }catch(error){
        console.log('can\'n load clean-css \n'                 +
            'to use images to base64 convertation you need to install css-base64-images \n'  +
                'npm install -g css-b64-images\n'                               +
                'https://github.com/Filirom1/css-base64-images');
        return false;
    }
    b64img.fromString(pFileContent_s, '.','', function(err, css){
        console.log('images converted to base64 and saved in css file');
        fs.writeFile(MinFolder + 'all.min.css', css, fileWrited(MinFolder + 'all.min.css'));
    });
}

/* Функция создаёт асинхроную версию
 * для чтения файла
 * @pFileName       - имя считываемого файла
 * @pProcessFunc    - функция обработки файла
 * @pLastFile_b     - последний файл?
 */
function fileReaded(pFileName,pProcessFunc, pLastFile_b){
    "use strict";
    return function(pError,pData){
        /* функция в которую мы попадаем,
         * если данные считались
         *
         * если ошибка - показываем её
         * иначе если переданная функция -
         * функция запускаем её
         */
        if(!pError)
            if (pProcessFunc && typeof pProcessFunc==="function")
                    pProcessFunc(pFileName,pData.toString(), pLastFile_b);
        else console.log(pError);
    };
}

/*
 * Функция вызываеться после записи файла
 * и выводит ошибку или сообщает,
 * что файл успешно записан
 */
function fileWrited(pFileName){
    "use strict";
    return function(error){
        console.log(error?error:('file '+pFileName+' writed...'));
    };
}

/*
 * Function reads hash table of files
 * checks is file changed or not
 * and return result.
 * @pFileName - name of file
 * @pFileData - data of file
 * result: boolean
 */
function isFileChanged(pFileName, pFileData, pLastFile_b){
        var lReadedHash;

        if(!Hashes)
            try {
                /* try to read file with hashes */
                Hashes = require('hashes.json');
                for(var lFileName in Hashes)
                    /* if founded row with file name
                     * saving hash
                     */
                    if (lFileName === pFileName) {
                        lReadedHash = Hashes[pFileName];
                        break;
                    }
            }catch(pError) {
                Hashes={};
            }
        /* create md5 hash of file data */
        var lFileHash = crypto.createHash('sha1');
        lFileHash.update(pFileData);
        lFileHash = lFileHash.digest('hex');

        console.log(pFileName + ': ' + lFileHash);

        if(lReadedHash &&
            lReadedHash === lFileHash){
                /* file did not change */
                return false;
        }else{
            Hashes[pFileName] = lFileHash;
            if(pLastFile_b)
                fs.writeFile('hashes.json', Hash, fileWrited(pLastFile_b));
            console.log(Hashes);

            return true;
        }
}<|endoftext|>


<commit_before>'use strict';

let cli = require('heroku-cli-util');
let archiver = require('archiver');
let fs = require('fs');
let ignore = require('ignore');
let uuid = require('node-uuid');
let os = require('os');
let path = require('path');
let request = require('request');

function uploadCwdToSource(app, cwd, fn) {
  let tempFilePath = path.join(os.tmpdir(), uuid.v4() + '.tar.gz');
  let ig = ignore().addIgnoreFile('.gitignore');
  let filter = ig.createFilter();

  app.sources().create({}).then(function(source){
    let archive = archiver('tar', { gzip: true });

    archive.on('finish', function (err) {
      if (err) { throw err; }

      let filesize = fs.statSync(tempFilePath).size;
      let request_options = {
        url: source.source_blob.put_url,
        headers: {
         'Content-Type': '',
         'Content-Length': filesize
        }
      };

      var stream = fs.createReadStream(tempFilePath);
      stream.on('close', function() {
        fs.unlink(tempFilePath);
      });

      stream.pipe(request.put(request_options, function() {
        fn(source.source_blob.get_url);
      }));
    });

    let output = fs.createWriteStream(tempFilePath);
    archive.pipe(output);
    var data = {};
    if (os.platform() === 'win32') {
      data.mode = 0o0755;
    }
    archive.bulk([
      { expand: true,
        cwd: cwd,
        src: ['**'],
        dest: false,
        filter: filter,
        data: data,
        dot: true
      }
    ]).finalize();
  });
}

function create(context, heroku) {
  let app = heroku.apps(context.app);

  var sourceUrl = context.args['source-url'];

  var sourceUrlPromise = sourceUrl ?
      new Promise(function(resolve) { resolve(sourceUrl);}) :
      new Promise(function(resolve) { uploadCwdToSource(app, context.cwd, resolve); });

  return sourceUrlPromise.then(function(sourceGetUrl) {
    return app.builds().create({
        source_blob: {
          url: sourceGetUrl,
          // TODO provide better default, eg. archive md5
          version: context.args.version || ''
        }
    });
  })
  .then(function(build) {
    request.get(build.output_stream_url).pipe(process.stderr);
  });
}

module.exports = {
  topic: 'builds',
  command: 'create',
  needsAuth: true,
  needsApp: true,
  help: 'Create build from contents of current dir',
  description: 'create build',
  flags: [
    { name: 'source-url', description: 'Source URL that points to the tarball of your application\'s source code', hasValue: true},
    { name: 'version', description: 'Description of your new build', hasValue: true }
  ],
  run: cli.command(create)
};
<commit_msg>Decrease indentation<commit_after>'use strict';

let cli = require('heroku-cli-util');
let archiver = require('archiver');
let fs = require('fs');
let ignore = require('ignore');
let uuid = require('node-uuid');
let os = require('os');
let path = require('path');
let request = require('request');

function uploadCwdToSource(app, cwd, fn) {
  let tempFilePath = path.join(os.tmpdir(), uuid.v4() + '.tar.gz');
  let ig = ignore().addIgnoreFile('.gitignore');
  let filter = ig.createFilter();

  app.sources().create({}).then(function(source){
    let archive = archiver('tar', { gzip: true });

    archive.on('finish', function (err) {
      if (err) { throw err; }

      let filesize = fs.statSync(tempFilePath).size;
      let request_options = {
        url: source.source_blob.put_url,
        headers: {
         'Content-Type': '',
         'Content-Length': filesize
        }
      };

      var stream = fs.createReadStream(tempFilePath);
      stream.on('close', function() {
        fs.unlink(tempFilePath);
      });

      stream.pipe(request.put(request_options, function() {
        fn(source.source_blob.get_url);
      }));
    });

    let output = fs.createWriteStream(tempFilePath);
    archive.pipe(output);
    var data = {};
    if (os.platform() === 'win32') {
      data.mode = 0o0755;
    }
    archive.bulk([
      { expand: true,
        cwd: cwd,
        src: ['**'],
        dest: false,
        filter: filter,
        data: data,
        dot: true
      }
    ]).finalize();
  });
}

function create(context, heroku) {
  let app = heroku.apps(context.app);

  var sourceUrl = context.args['source-url'];

  var sourceUrlPromise = sourceUrl ?
      new Promise(function(resolve) { resolve(sourceUrl);}) :
      new Promise(function(resolve) { uploadCwdToSource(app, context.cwd, resolve); });

  return sourceUrlPromise.then(function(sourceGetUrl) {
    return app.builds().create({
      source_blob: {
        url: sourceGetUrl,
        // TODO provide better default, eg. archive md5
        version: context.args.version || ''
      }
    });
  })
  .then(function(build) {
    request.get(build.output_stream_url).pipe(process.stderr);
  });
}

module.exports = {
  topic: 'builds',
  command: 'create',
  needsAuth: true,
  needsApp: true,
  help: 'Create build from contents of current dir',
  description: 'create build',
  flags: [
    { name: 'source-url', description: 'Source URL that points to the tarball of your application\'s source code', hasValue: true},
    { name: 'version', description: 'Description of your new build', hasValue: true }
  ],
  run: cli.command(create)
};
<|endoftext|>


<commit_before>import BaseProvider from '../base_provider';
import VimeoModel from './vimeo_model';
import {PROVIDERS_LIST} from '../../../../constants/providers';

/**
 * @see: https://developer.vimeo.com/player/embedding
 */
class VimeoProvider extends BaseProvider {
    static CLASS = 'VimeoProvider';

    el = null;
    PROVIDER = PROVIDERS_LIST.VIMEO;
    vimeoPath = '//player.vimeo.com/video/';

    getPlayerContainer() {
        if (null !== this.el) return this.el;

        this._initPlayer();

        this.el = document.createElement('iframe');
        this.el.id = VimeoProvider.CLASS;
        this.el.src = this.vimeoPath;
        this.el.width = this.config.width;
        this.el.height = this.config.height;

        return this.el;
    }

    _initPlayer() {
        // events?
    }

    render() {
        return this.getPlayerContainer();
    }

    setModel(song) {
        this.model = VimeoModel.create(song);

        return this;
    }

    /**
     *
     */
    play() {
        console.log(this);
    }
}

export default VimeoProvider;<commit_msg>vimeo froogaloop2 added<commit_after>import BaseProvider from '../base_provider';
import VimeoModel from './vimeo_model';
import {PROVIDERS_LIST} from '../../../../constants/providers';

/**
 * @see: https://developer.vimeo.com/player/embedding
 * @see: https://player.vimeo.com/playground
 */
class VimeoProvider extends BaseProvider {
    static CLASS = 'VimeoProvider';

    playerOrigin = '*';
    player = null;
    el = null;
    PROVIDER = PROVIDERS_LIST.VIMEO;
    vimeoPath = '//player.vimeo.com/video/{{VIDEO_ID}}?api=1&player_id=VimeoProvider';

    init() {
        this.scriptLoad();
    }

    /**
     *
     */
    scriptLoad() {
        let tag = document.createElement('script'),
            firstScriptTag = document.getElementsByTagName('script')[0];

        tag.src = 'https://f.vimeocdn.com/js/froogaloop2.min.js';
        tag.onload = this._initPlayer.bind(this);

        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

        return this;
    }

    getPlayerContainer() {
        if (null !== this.el) return this.el;

        this.el = document.createElement('iframe');
        this.el.id = VimeoProvider.CLASS;
        this.el.src = this.vimeoPath;
        this.el.width = this.config.width;
        this.el.height = this.config.height;

        return this.el;
    }

    _initPlayer() {
        if (window.addEventListener) {
            window.addEventListener('message', this.onMessageReceived.bind(this), false);
        }
        else {
            window.attachEvent('onmessage', this.onMessageReceived.bind(this), false);
        }

        this.player = $f(VimeoProvider.CLASS);
    }

    onMessageReceived(event) {
        // Handle messages from the vimeo player only
        if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
            return false;
        }

        if (this.playerOrigin === '*') {
            this.playerOrigin = event.origin;
        }

        var data = JSON.parse(event.data);

        switch (data.event) {
            case 'ready':
                this.onReady();
                break;

            case 'playProgress':
                this.onPlayProgress(data.data);
                break;

            case 'pause':
                this.onPause();
                break;

            case 'finish':
                this.onFinish();
                break;
        }
    }

    // Helper function for sending a message to the player
    post(action, value) {
        var data = {
          method: action
        };

        if (value) {
            data.value = value;
        }

        var message = JSON.stringify(data);
        this.getPlayerContainer().contentWindow.postMessage(message, this.playerOrigin);
    }

    onReady() {
        console.log('ready');
        this.player.api('play');

        this.post('addEventListener', 'pause');
        this.post('addEventListener', 'finish');
        this.post('addEventListener', 'playProgress');
    }

    onPause() {
        console.log('paused');
    }

    onFinish() {
        console.log('finished');
    }

    onPlayProgress(data) {
        console.log(data.seconds + 's played');
    }

    render() {
        return this.getPlayerContainer();
    }

    setModel(song) {
        this.model = VimeoModel.create(song);

        return this;
    }

    /**
     *
     */
    play() {
        this.el.src = this.vimeoPath.replace('{{VIDEO_ID}}', this.model.id);
    }
}

export default VimeoProvider;<|endoftext|>


<commit_before>'use strict';

var aFrom        = require('es5-ext/array/from')
  , compact      = require('es5-ext/array/#/compact')
  , isCopy       = require('es5-ext/array/#/is-copy')
  , copy         = require('es5-ext/object/copy')
  , assign       = require('es5-ext/object/assign')
  , isObject     = require('es5-ext/object/is-object')
  , callable     = require('es5-ext/object/valid-callable')
  , toArray      = require('es6-iterator/to-array')
  , d            = require('d/d')
  , memoize      = require('memoizee/lib/regular')
  , memPrimitive = require('memoizee/lib/primitive')
  , makeEl       = require('dom-ext/document/#/make-element')
  , append       = require('dom-ext/element/#/append')
  , clear        = require('dom-ext/element/#/clear')
  , remove       = require('dom-ext/element/#/remove')
  , replaceCont  = require('dom-ext/element/#/replace-content')
  , dispatchEvnt = require('dom-ext/html-element/#/dispatch-event-2')
  , DOMInput     = require('../_controls/input')
  , eventOpts    = require('../_event-options')
  , setup        = require('../')

  , isArray = Array.isArray, map = Array.prototype.map
  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , getName = Object.getOwnPropertyDescriptor(DOMInput.prototype, 'name').get
  , Input, render, renderItem;

require('memoizee/lib/ext/method');

render = function (options) {
	var el = this.make;
	return el('div', { class: 'dbjs-file' },
		this.valueDOM = this.multiple ? el('ul') : el('span'),
		el('label', { class: 'dbjs-file-input' }, options.label,
			this.control = el('input', { type: 'file' })));
};

renderItem = function (file) {
	var el = this.make, data = {};
	data.dom = el(this.multiple ? 'li' : 'span', { 'data-id': file.__id__ });
	append.call(data.dom,
		el('a', { href: file._url, target: '_blank' }, file._name), " ",
		data.control = el('input', { type: 'hidden', name: this.name,
			value: file.__id__ }),
		el('a', { class: 'clear', onclick: this.removeItem.bind(this, data.dom) },
			"x"));
	return data;
};

Input = function (document, type/*, options*/) {
	var options = arguments[2];
	this.make = makeEl.bind(document);
	this.controls = [];
	this.type = type;
	options = this._resolveOptions(options);
	if (options.multiple) this.multiple = true;
	((options.render == null) || callable(options.render));
	defineProperty(this, 'renderItem', d((options.renderItem == null) ?
			renderItem : callable(options.renderItem)));
	DOMInput.call(this, document, type, options);
	if (this.multiple) this.control.setAttribute('multiple', 'multiple');
	this.control.setAttribute('accept', toArray(type.accept).join(','));
};

Input.prototype = Object.create(DOMInput.prototype, assign({
	constructor: d(Input),
	multiple: d(false),
	_value: d(null),
	controlAttributes: d(assign(copy(DOMInput.prototype.controlAttributes),
		{ required: true })),
	dbAttributes: d(assign(copy(DOMInput.prototype.dbAttributes),
		{ required: true })),
	_render: d(function (options) {
		this.dom = (options.render || render).call(this, options);
		this.controls.push(this.control);
	}),
	name: d.gs(getName, function (name) {
		this._name = name;
		name = this.name;
		this.controls.forEach(function (input) { input.name = name; });
	}),
	inputValue: d.gs(function () {
		var value;
		if (!this.multiple) {
			if (this.control.files[0]) return this.control.files[0];
			if (!this.valueDOM.firstElementChild) return null;
			return this.valueDOM.firstElementChild.getAttribute('data-id');
		}
		value = map.call(this.valueDOM.childNodes, function (node) {
			var id = node.getAttribute('data-id');
			if (!id) {
				throw new TypeError("Missing id (data-id attribute) on file item");
			}
			return id;
		}).concat(aFrom(this.control.files));
		return value.length ? value : null;
	}, function (nu) {
		var old = this.inputValue, changed;
		this._value = nu;
		if (this.multiple) {
			if (nu) {
				if (!old || !isCopy.call(nu, old)) {
					this.control.value = null;
					replaceCont.call(this.valueDOM, nu.map(this._renderItem));
					changed = true;
				}
			} else {
				clear.call(this.valueDOM);
			}
		} else if (nu !== old) {
			this.control.value = null;
			if (nu) {
				replaceCont.call(this.valueDOM, this._renderItem(nu));
				this.dom.classList.add('filled');
			} else {
				clear.call(this.valueDOM);
				this.dom.classList.remove('filled');
			}
			changed = true;
		}
		if (changed) {
			try {
				dispatchEvnt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
	}),
	value: d.gs(function () {
		var value = this.inputValue;
		if (value == null) return null;
		if (this.multiple) return value.map(this.type.toInputValue, this.type);
		return this.type.toInputValue(value);
	}, function (value) {
		if (value == null) {
			value = null;
		} else if (this.multiple) {
			value = toArray(value);
			if (value.length) {
				value = compact.call(value.map(this.type.toInputValue, this.type));
			}
			if (!value.length) value = null;
		} else {
			value = this.type.toInputValue(value);
		}

		this.inputValue = value;
	}),
	onChange: d(function () {
		var value, changed, valid, emitChanged, emitValid;
		value = this.inputValue;
		changed = (this.multiple && (this._value != null) && (value != null)) ?
				isCopy.call(value, this._value) : (value !== this._value);
		valid = this.required ? (value != null) : true;

		if (this.changed !== changed) {
			this.changed = changed;
			emitChanged = true;
		}
		if (this.valid !== valid) {
			this.valid = valid;
			emitValid = true;
		}

		this.emit('change', value);
		if (emitChanged) this.emit('change:changed', this.changed);
		if (emitValid) this.emit('change:valid', this.valid);
	}),
	removeItem: d(function (dom) {
		remove.call(dom);
		if (!this.multiple) this.dom.classList.remove('filled');
		dispatchEvnt.call(this.control, 'change', eventOpts);
	})
}, memPrimitive(function (file) {
	var data;
	file = this.type.getById(file);
	data = this.renderItem(file);
	this.controls.push(data.control);
	return data.dom;
}, { method: '_renderItem' })));

module.exports = memoize(function (db) {
	defineProperties(setup(db).File, {
		fromInputValue: d(function (value) {
			if (value == null) return null;
			if (isArray(value) && (value.length === 2)) {
				if (typeof value[0] === 'string') {
					if (isObject(value[1])) return value[1];
				} else if (typeof value[1] === 'string') {
					if (isObject(value[0])) return value[0];
				}
				return value;
			}
			if (isObject(value)) return value;
			value = value.trim();
			if (!value) return null;
			return this.getById(value);
		}),
		DOMInput: d(Input),
		toDOMInput: d(function (document/*, options*/) {
			var options = Object(arguments[1]);
			if (options.multiple || (options.type !== 'checkbox')) {
				return new this.DOMInput(document, this, options);
			}
			return db.Object.toDOMInput(document, options);
		})
	});
});

exports.Input = Input;
<commit_msg>-- lint<commit_after>'use strict';

var aFrom        = require('es5-ext/array/from')
  , compact      = require('es5-ext/array/#/compact')
  , isCopy       = require('es5-ext/array/#/is-copy')
  , copy         = require('es5-ext/object/copy')
  , assign       = require('es5-ext/object/assign')
  , isObject     = require('es5-ext/object/is-object')
  , callable     = require('es5-ext/object/valid-callable')
  , toArray      = require('es6-iterator/to-array')
  , d            = require('d/d')
  , memoize      = require('memoizee/lib/regular')
  , memPrimitive = require('memoizee/lib/primitive')
  , makeEl       = require('dom-ext/document/#/make-element')
  , append       = require('dom-ext/element/#/append')
  , clear        = require('dom-ext/element/#/clear')
  , remove       = require('dom-ext/element/#/remove')
  , replaceCont  = require('dom-ext/element/#/replace-content')
  , dispatchEvnt = require('dom-ext/html-element/#/dispatch-event-2')
  , DOMInput     = require('../_controls/input')
  , eventOpts    = require('../_event-options')
  , setup        = require('../')

  , isArray = Array.isArray, map = Array.prototype.map
  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , getName = Object.getOwnPropertyDescriptor(DOMInput.prototype, 'name').get
  , Input, render, renderItem;

require('memoizee/lib/ext/method');

render = function (options) {
	var el = this.make;
	return el('div', { class: 'dbjs-file' },
		this.valueDOM = this.multiple ? el('ul') : el('span'),
		el('label', { class: 'dbjs-file-input' }, options.label,
			this.control = el('input', { type: 'file' })));
};

renderItem = function (file) {
	var el = this.make, data = {};
	data.dom = el(this.multiple ? 'li' : 'span', { 'data-id': file.__id__ });
	append.call(data.dom,
		el('a', { href: file._url, target: '_blank' }, file._name), " ",
		data.control = el('input', { type: 'hidden', name: this.name,
			value: file.__id__ }),
		el('a', { class: 'clear', onclick: this.removeItem.bind(this, data.dom) },
			"x"));
	return data;
};

Input = function (document, type/*, options*/) {
	var options = arguments[2];
	this.make = makeEl.bind(document);
	this.controls = [];
	this.type = type;
	options = this._resolveOptions(options);
	if (options.multiple) this.multiple = true;
	((options.render == null) || callable(options.render));
	defineProperty(this, 'renderItem', d((options.renderItem == null)
		? renderItem : callable(options.renderItem)));
	DOMInput.call(this, document, type, options);
	if (this.multiple) this.control.setAttribute('multiple', 'multiple');
	this.control.setAttribute('accept', toArray(type.accept).join(','));
};

Input.prototype = Object.create(DOMInput.prototype, assign({
	constructor: d(Input),
	multiple: d(false),
	_value: d(null),
	controlAttributes: d(assign(copy(DOMInput.prototype.controlAttributes),
		{ required: true })),
	dbAttributes: d(assign(copy(DOMInput.prototype.dbAttributes),
		{ required: true })),
	_render: d(function (options) {
		this.dom = (options.render || render).call(this, options);
		this.controls.push(this.control);
	}),
	name: d.gs(getName, function (name) {
		this._name = name;
		name = this.name;
		this.controls.forEach(function (input) { input.name = name; });
	}),
	inputValue: d.gs(function () {
		var value;
		if (!this.multiple) {
			if (this.control.files[0]) return this.control.files[0];
			if (!this.valueDOM.firstElementChild) return null;
			return this.valueDOM.firstElementChild.getAttribute('data-id');
		}
		value = map.call(this.valueDOM.childNodes, function (node) {
			var id = node.getAttribute('data-id');
			if (!id) {
				throw new TypeError("Missing id (data-id attribute) on file item");
			}
			return id;
		}).concat(aFrom(this.control.files));
		return value.length ? value : null;
	}, function (nu) {
		var old = this.inputValue, changed;
		this._value = nu;
		if (this.multiple) {
			if (nu) {
				if (!old || !isCopy.call(nu, old)) {
					this.control.value = null;
					replaceCont.call(this.valueDOM, nu.map(this._renderItem));
					changed = true;
				}
			} else {
				clear.call(this.valueDOM);
			}
		} else if (nu !== old) {
			this.control.value = null;
			if (nu) {
				replaceCont.call(this.valueDOM, this._renderItem(nu));
				this.dom.classList.add('filled');
			} else {
				clear.call(this.valueDOM);
				this.dom.classList.remove('filled');
			}
			changed = true;
		}
		if (changed) {
			try {
				dispatchEvnt.call(this.control, 'change', eventOpts);
			} catch (ignore) {}
		} else {
			this.onChange();
		}
	}),
	value: d.gs(function () {
		var value = this.inputValue;
		if (value == null) return null;
		if (this.multiple) return value.map(this.type.toInputValue, this.type);
		return this.type.toInputValue(value);
	}, function (value) {
		if (value == null) {
			value = null;
		} else if (this.multiple) {
			value = toArray(value);
			if (value.length) {
				value = compact.call(value.map(this.type.toInputValue, this.type));
			}
			if (!value.length) value = null;
		} else {
			value = this.type.toInputValue(value);
		}

		this.inputValue = value;
	}),
	onChange: d(function () {
		var value, changed, valid, emitChanged, emitValid;
		value = this.inputValue;
		changed = (this.multiple && (this._value != null) && (value != null))
			? isCopy.call(value, this._value) : (value !== this._value);
		valid = this.required ? (value != null) : true;

		if (this.changed !== changed) {
			this.changed = changed;
			emitChanged = true;
		}
		if (this.valid !== valid) {
			this.valid = valid;
			emitValid = true;
		}

		this.emit('change', value);
		if (emitChanged) this.emit('change:changed', this.changed);
		if (emitValid) this.emit('change:valid', this.valid);
	}),
	removeItem: d(function (dom) {
		remove.call(dom);
		if (!this.multiple) this.dom.classList.remove('filled');
		dispatchEvnt.call(this.control, 'change', eventOpts);
	})
}, memPrimitive(function (file) {
	var data;
	file = this.type.getById(file);
	data = this.renderItem(file);
	this.controls.push(data.control);
	return data.dom;
}, { method: '_renderItem' })));

module.exports = memoize(function (db) {
	defineProperties(setup(db).File, {
		fromInputValue: d(function (value) {
			if (value == null) return null;
			if (isArray(value) && (value.length === 2)) {
				if (typeof value[0] === 'string') {
					if (isObject(value[1])) return value[1];
				} else if (typeof value[1] === 'string') {
					if (isObject(value[0])) return value[0];
				}
				return value;
			}
			if (isObject(value)) return value;
			value = value.trim();
			if (!value) return null;
			return this.getById(value);
		}),
		DOMInput: d(Input),
		toDOMInput: d(function (document/*, options*/) {
			var options = Object(arguments[1]);
			if (options.multiple || (options.type !== 'checkbox')) {
				return new this.DOMInput(document, this, options);
			}
			return db.Object.toDOMInput(document, options);
		})
	});
});

exports.Input = Input;
<|endoftext|>


<commit_before>(function () {
  'use strict';

  function TcPjaxBundle() {
    var _this = this;

    _this.containers = $( '[data-pjax-container]' );
    _this.config = {
      version: 1,
      timeout: 2000
    };

    if ( typeof $ === 'undefined' ) {
      if ( typeof console !== 'undefined' ) {
        console.error( 'TcPjaxBundle is dependant on jQuery' );
      }
    } else if ( typeof $.pjax === 'undefined' ) {
      if ( typeof console !== 'undefined' ) {
        console.error( 'TcPjaxBundle is dependant on PJAX' );
      }
    } else {

      if ( _this.containers.length > 0 ) {
        _this.config.version = $( _this.containers[ 0 ] ).attr( 'data-pjax-version' );
        _this.config.timeout = $( _this.containers[ 0 ] ).attr( 'data-pjax-timeout' );
      }

      if ( typeof $.pjax.defaults !== 'undefined' ) {
        $.pjax.defaults.timeout = _this.config.timeout;
        $.pjax.defaults.version = _this.config.version;
      }

	    if (typeof angular !== 'undefined') {
		    _this.angularRefresh = function(container) {
			    var scope = angular.element(container).scope();
			    var compile = angular.element(container).injector().get('$compile');
			    compile($(container).contents())(scope);
			    scope.$apply();
		    }
	    }

      _this.containers.each( function () {
        if ( !$( this ).attr( 'data-pjax-disable' ) ) {
	        var container = '#' + $( this ).attr( 'data-pjax-container' );
          $( document ).pjax( 'a', container );
	        if (typeof _this.angularRefresh !== 'undefined') {
		        $( document ).on('pjax:success', function(e){
			        _this.angularRefresh(container);
		        });
	        }
        }
      } );

    }
  }

  new TcPjaxBundle();

})();
<commit_msg>add no-pjax attribute<commit_after>(function () {
  'use strict';

  function TcPjaxBundle() {
    var _this = this;

    _this.containers = $( '[data-pjax-container]' );
    _this.config = {
      version: 1,
      timeout: 2000
    };

    if ( typeof $ === 'undefined' ) {
      if ( typeof console !== 'undefined' ) {
        console.error( 'TcPjaxBundle is dependant on jQuery' );
      }
    } else if ( typeof $.pjax === 'undefined' ) {
      if ( typeof console !== 'undefined' ) {
        console.error( 'TcPjaxBundle is dependant on PJAX' );
      }
    } else {

      if ( _this.containers.length > 0 ) {
        _this.config.version = $( _this.containers[ 0 ] ).attr( 'data-pjax-version' );
        _this.config.timeout = $( _this.containers[ 0 ] ).attr( 'data-pjax-timeout' );
      }

      if ( typeof $.pjax.defaults !== 'undefined' ) {
        $.pjax.defaults.timeout = _this.config.timeout;
        $.pjax.defaults.version = _this.config.version;
      }

	    if (typeof angular !== 'undefined') {
		    _this.angularRefresh = function(container) {
			    var scope = angular.element(container).scope();
			    var compile = angular.element(container).injector().get('$compile');
			    compile($(container).contents())(scope);
			    scope.$apply();
		    }
	    }

      _this.containers.each( function () {
        if ( !$( this ).attr( 'data-pjax-disable' ) ) {
	        var container = '#' + $( this ).attr( 'data-pjax-container' );
          $( document ).pjax( 'a:not([no-pjax])', container );
	        if (typeof _this.angularRefresh !== 'undefined') {
		        $( document ).on('pjax:success', function(e){
			        _this.angularRefresh(container);
		        });
	        }
        }
      } );

    }
  }

  new TcPjaxBundle();

})();
<|endoftext|>