<commit_before>/*jshint globalstrict:false, strict:false, maxlen: 500 */
/*global assertEqual */

////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, geo queries
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var jsunity = require("jsunity");
var internal = require("internal");
var db = require("@arangodb").db;
var errors = require("@arangodb").errors;
var helper = require("@arangodb/aql-helper");
var getQueryResults = helper.getQueryResults;
var assertQueryError = helper.assertQueryError;

////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////

function ahuacatlGeoTestSuite () {
  var locations = null;

  function runQuery (query) {
    var result = getQueryResults(query);

    result = result.map(function(row) {
      var r;
      if (row !== null && typeof row === 'object') {
        for (r in row) {
          if (row.hasOwnProperty(r)) {
            var value = row[r];
            if (typeof(value) === "number") {
              if (value !== parseFloat(parseInt(value))) {
                row[r] = Number(value).toFixed(5);
              }
            }
          }
        }
      }

      return row;
    });

    return result;
  }

  return {

////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////

    setUp : function () {
      var lat, lon;

      var pre = internal.time();
      db._drop("UnitTestsAhuacatlLocations");
      var after = internal.time();
      internal.print("Drop: " + (after - pre) + " s");

      pre = internal.time();
      locations = db._create("UnitTestsAhuacatlLocations");
      after = internal.time();
      internal.print("Create: " + (after - pre) + " s");

      for (lat = -40; lat <= 40; ++lat) {
        for (lon = -40; lon <= 40; ++lon) {
          locations.save({"latitude" : lat, "longitude" : lon });
        }
      }

      pre = internal.time();
      locations.ensureGeoIndex("latitude", "longitude");
      after = internal.time();
      internal.print("Insert: " + (after - pre) + " s");

    },

////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////

    tearDown : function () {
      db._drop("UnitTestsAhuacatlLocations");
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test near function
////////////////////////////////////////////////////////////////////////////////

    testNear1 : function () {
      var expected = [ { "distance" : "111194.92664", "latitude" : -1, "longitude" : 0 }, { "distance" : "111194.92664", "latitude" : 0, "longitude" : -1 }, { "distance" : "111194.92664", "latitude" : 0, "longitude" : 1 }, { "distance" : "111194.92664", "latitude" : 1, "longitude" : 0 }, { "distance" : 0, "latitude" : 0, "longitude" : 0 } ];
      var pre = internal.time();

      var actual = runQuery("FOR x IN NEAR(" + locations.name() + ", 0, 0, 5, \"distance\") SORT x.distance DESC, x.latitude, x.longitude RETURN x");

      var after = internal.time();
            internal.print("Cursor 1: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test near function
////////////////////////////////////////////////////////////////////////////////

    testNear2 : function () {
      var expected = [ { "latitude" : -10, "longitude" : 24 }, { "latitude" : -10, "longitude" : 25 }, { "latitude" : -10, "longitude" : 26 } ];
            var pre = internal.time();

      var actual = runQuery("FOR x IN NEAR(" + locations.name() + ", -10, 25, 3) SORT x.latitude, x.longitude RETURN x");
            var after = internal.time();
            internal.print("Cursor 2: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test near function
////////////////////////////////////////////////////////////////////////////////

    testNear3 : function () {
      var expected = [ { "distance" : "14891044.54146", "latitude" : 40, "longitude" : -40 }, { "distance" : "14853029.30724", "latitude" : 40, "longitude" : -39 }, { "distance" : "14815001.47646", "latitude" : 40, "longitude" : -38 } ];
      var pre = internal.time();
      var actual = runQuery("FOR x IN NEAR(" + locations.name() + ", -70, 70, 10000, \"distance\") SORT x.distance DESC LIMIT 3 RETURN x");
      var after = internal.time();
      internal.print("Cursor 3: " + (after - pre) + " s");
      assertEqual(expected, actual);

      expected = [ {"distance" : "4487652.12954", "latitude" : -37, "longitude" : 26 }, { "distance" : "4485565.93668", "latitude" : -39, "longitude" : 20 }, { "distance" : "4484371.86154" , "latitude" : -38, "longitude" : 23 } ];
      pre = internal.time();
      actual = runQuery("FOR x IN NEAR(" + locations.name() + ", -70, 70, null, \"distance\") SORT x.distance DESC LIMIT 3 RETURN x");
      after = internal.time();
      internal.print("Cursor 4: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test near function
////////////////////////////////////////////////////////////////////////////////

    testNear4 : function () {
      var expected = [ {"latitude" : -40, "longitude" : 40 }, { "latitude" : -40, "longitude" : 39 }, { "latitude" : -40, "longitude" : 38 } ];
      var actual = runQuery("FOR x IN NEAR(" + locations.name() + ", -70, 70, null) SORT x.latitude, x.longitude DESC LIMIT 3 RETURN x");
      assertEqual(expected, actual);

      expected = [ { "latitude" : -40, "longitude" : 40 }, { "latitude" : -40, "longitude" : 39 } ];
      actual = runQuery("FOR x IN NEAR(" + locations.name() + ", -70, 70, 2) SORT x.latitude, x.longitude DESC LIMIT 3 RETURN x");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test within function
////////////////////////////////////////////////////////////////////////////////

    testWithin1 : function () {
      var expected = [ { "distance" : 0, "latitude" : 0, "longitude" : 0 } ];
      var pre = internal.time();
      var actual = runQuery("FOR x IN WITHIN(" + locations.name() + ", 0, 0, 10000, \"distance\") SORT x.latitude, x.longitude RETURN x");
      var after = internal.time();
      internal.print("Radius 1: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test within function
////////////////////////////////////////////////////////////////////////////////

    testWithin2 : function () {
      var expected = [ { "distance" : "111194.92664", "latitude" : -1, "longitude" : 0 }, { "distance" : "111194.92664", "latitude" : 0, "longitude" : -1 }, { "distance" : 0, "latitude" : 0, "longitude" : 0 }, { "distance" : "111194.92664", "latitude" : 0, "longitude" : 1 }, { "distance" : "111194.92664", "latitude" : 1, "longitude" : 0 } ];
            var pre = internal.time();
      var actual = runQuery("FOR x IN WITHIN(" + locations.name() + ", 0, 0, 150000, \"distance\") SORT x.latitude, x.longitude RETURN x");
      var after = internal.time();
      internal.print("Radius 2: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test within function
////////////////////////////////////////////////////////////////////////////////

    testWithin3 : function () {
      var expected = [ { "latitude" : -10, "longitude" : 25 } ];
                  var pre = internal.time();

      var actual = runQuery("FOR x IN WITHIN(" + locations.name() + ", -10, 25, 10000) SORT x.latitude, x.longitude RETURN x");
      var after = internal.time();
      internal.print("Radius 3: " + (after - pre) + " s");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test within function
////////////////////////////////////////////////////////////////////////////////

    testWithin4 : function () {
      var expected = [
        { "latitude" : -11, "longitude" : 25 },
        { "latitude" : -10, "longitude" : 24 },
        { "latitude" : -10, "longitude" : 25 },
        { "latitude" : -10, "longitude" : 26 },
        { "latitude" : -9, "longitude" : 25 }
      ];

      var actual = runQuery("FOR x IN WITHIN(" + locations.name() + ", -10, 25, 150000) SORT x.latitude, x.longitude RETURN x");
      assertEqual(expected, actual);
    },

////////////////////////////////////////////////////////////////////////////////
/// @brief test within function
////////////////////////////////////////////////////////////////////////////////

    testWithin5 : function () {
      var expected = [ ];
      var actual = runQuery("FOR x IN WITHIN(" + locations.name() + ", -90, 90, 10000) SORT x.latitude, x.longitude RETURN x");
      assertEqual(expected, actual);
    }
  };
}

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////

jsunity.run(ahuacatlGeoTestSuite);

return jsunity.done();

<commit_msg>Removed debug test<commit_after><|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import Reflux from 'reflux';
import TagsInput from 'react-tagsinput';
import stores from '../stores';
import actions from '../actions';
import mixins from '../mixins';
import classNames from 'classnames';
import Select from 'react-select';
import bem from '../bem';
import {
  t,
  parsePermissions,
  getAnonymousUserPermission,
  stringToColor,
  anonUsername
} from '../utils';

var UserPermDiv = React.createClass({
  mixins: [
    mixins.permissions,
  ],
  PermOnChange(perm) {
    var cans = this.props.can;
    if (perm) {
      var permName = perm.value;
      this.setPerm(permName, this.props);
      if (permName == 'view' && cans.change)
        this.removePerm('change', cans.change, this.props.uid);
    } else {
      if (cans.view)
        this.removePerm('view', cans.view, this.props.uid);
      if (cans.change)
        this.removePerm('change', cans.change, this.props.uid);
    }

  },
  render () {
    var initialsStyle = {
      background: `#${stringToColor(this.props.username)}`
    };

    var currentPerm = '';
    var cans = this.props.can;

    if (cans.change) {
      var currentPerm = 'change';
    } else if (cans.view) {
      var currentPerm = 'view';
    }

    var availablePermissions = [
      {value: 'view', label: t('Can View')},
      {value: 'change', label: t('Can Edit')}
    ];

    return (
      <bem.UserRow m={cans.view || cans.change ? 'regular' : 'deleted'}>
        <bem.UserRow__avatar>
          <bem.AccountBox__initials style={initialsStyle}>
            {this.props.username.charAt(0)}
          </bem.AccountBox__initials>
        </bem.UserRow__avatar>
        <bem.UserRow__name>
          {this.props.username}
          {/*
<UserProfileLink username= />
*/}
        </bem.UserRow__name>
        <bem.UserRow__role>
          <Select
            name='userPerms'
            value={currentPerm}
            clearable={true}
            options={availablePermissions}
            onChange={this.PermOnChange}
          />
        </bem.UserRow__role>
      </bem.UserRow>
      );
  }
});

var PublicPermDiv = React.createClass({
  mixins: [
    mixins.permissions
  ],
  togglePerms() {
    if (this.props.publicPerm)
      this.removePerm('view',this.props.publicPerm, this.props.uid);
    else
      this.setPerm('view', {
          username: anonUsername,
          uid: this.props.uid,
          kind: this.props.kind,
          objectUrl: this.props.objectUrl
        }
      );
  },
  render () {
    var uid = this.props.uid;

    var href = `forms/${uid}`;
    var url = `${window.location.protocol}//${window.location.host}/${href}`;

    return (
      <bem.FormModal__item m='perms-link'>
        <input  type="checkbox"
                checked={this.props.publicPerm ? true : false}
                onChange={this.togglePerms}
                id="share-by-link"/>
        {t('Share by link')}
        { this.props.publicPerm &&
          <bem.FormModal__item m='shareable-link'>

              {t('Shareable link')}

            <input type="text" value={url} readOnly />
          </bem.FormModal__item>
        }
      </bem.FormModal__item>
    );
  }
});

var SharingForm = React.createClass({
  mixins: [
    mixins.permissions,
    mixins.contextRouter,
    Reflux.ListenerMixin
  ],
  assetChange (data) {
    var uid = this.props.uid || this.currentAssetID(),
      asset = data[uid];

    if (asset) {
      this.setState({
        asset: asset,
        permissions: asset.permissions,
        owner: asset.owner__username,
        pperms: parsePermissions(asset.owner__username, asset.permissions),
        public_permission: getAnonymousUserPermission(asset.permissions),
        related_users: stores.asset.relatedUsers[uid]
      });
    }
  },
  componentDidMount () {
    this.listenTo(stores.userExists, this.userExistsStoreChange);
    if (this.props.uid) {
      actions.resources.loadAsset({id: this.props.uid});
    }
    this.listenTo(stores.asset, this.assetChange);
  },
  userExistsStoreChange (checked, result) {
    var inpVal = this.usernameFieldValue();
    if (inpVal === result) {
      var newStatus = checked[result] ? 'success' : 'error';
      this.setState({
        userInputStatus: newStatus
      });
    }
  },
  usernameField () {
    return ReactDOM.findDOMNode(this.refs.usernameInput);
  },
  usernameFieldValue () {
    return this.usernameField().value;
  },
  usernameCheck (evt) {
    var username = evt.target.value;
    if (username && username.length > 1) {
      var result = stores.userExists.checkUsername(username);
      if (result === undefined) {
        actions.misc.checkUsername(username);
      } else {
        log(result ? 'success' : 'error');
        this.setState({
          userInputStatus: result ? 'success' : 'error'
        });
      }
    } else {
      this.setState({
        userInputStatus: false
      });
    }
  },
  getInitialState () {
    return {
      userInputStatus: false,
      permInput: 'view'
    };
  },
  addInitialUserPermission (evt) {
    evt.preventDefault();
    var username = this.usernameFieldValue();
    if (stores.userExists.checkUsername(username)) {
      actions.permissions.assignPerm({
        username: username,
        uid: this.state.asset.uid,
        kind: this.state.asset.kind,
        objectUrl: this.props.objectUrl,
        role: this.state.permInput
      });
      this.usernameField().value = '';
    }
  },
  updatePermInput(permName) {
    this.setState({
      permInput: permName.value
    });
  },
  render () {
    var inpStatus = this.state.userInputStatus;
    if (!this.state.pperms) {
      return (
          <bem.Loading>
            <bem.Loading__inner>

              {t('loading...')}
            </bem.Loading__inner>
          </bem.Loading>
        );
    }
    var _perms = this.state.pperms;
    var perms = this.state.related_users.map(function(username){
      var currentPerm = _perms.filter(function(p){
        return p.username === username;
      })[0];
      if (currentPerm) {
        return currentPerm;
      } else {
        return {
          username: username,
          can: {}
        };
      }
    });
    var btnKls = classNames('mdl-button','mdl-js-button', 'mdl-button--raised', inpStatus === 'success' ? 'mdl-button--colored' : 'mdl-button--disabled');

    var availablePermissions = [
      {value: 'view', label: t('Can View')},
      {value: 'change', label: t('Can Edit')}
    ];

    var uid = this.state.asset.uid;
    var kind = this.state.asset.kind;
    var asset_type = this.state.asset.asset_type;
    var objectUrl = this.state.asset.url;

    if (!perms) {
      return (

loading

        );
    }

    var initialsStyle = {
      background: `#${stringToColor(this.state.asset.owner__username)}`
    };

    return (
      <bem.FormModal>
        <bem.FormModal__item>
          <bem.FormView__cell m='label'>
            {t('Who has access')}
          </bem.FormView__cell>
          <bem.UserRow>
            <bem.UserRow__avatar>
              <bem.AccountBox__initials style={initialsStyle}>
                {this.state.asset.owner__username.charAt(0)}
              </bem.AccountBox__initials>
            </bem.UserRow__avatar>
            <bem.UserRow__name>

{this.state.asset.owner__username}

            </bem.UserRow__name>
            <bem.UserRow__role>{t('is owner')}</bem.UserRow__role>
          </bem.UserRow>

          {perms.map((perm)=> {
            return <UserPermDiv key={`perm.${uid}.${perm.username}`} ref={perm.username} uid={uid} kind={kind} objectUrl={objectUrl} {...perm} />;
          })}

        </bem.FormModal__item>

        <bem.FormModal__form onSubmit={this.addInitialUserPermission} className="sharing-form__user">
            <bem.FormView__cell m='label'>
              {t('Invite collaborators')}
            </bem.FormView__cell>
            <bem.FormModal__item m='perms-user'>
              <input type="text"
                  id="permsUser"
                  ref='usernameInput'
                  placeholder={t('Enter a username')}
                  onKeyUp={this.usernameCheck}
                  onChange={this.usernameCheck}
              />
              <Select
                  id='permGiven'
                  ref='permInput'
                  value={this.state.permInput}
                  clearable={false}
                  options={availablePermissions}
                  onChange={this.updatePermInput}
              />
              <button className={btnKls}>
                  {t('invite')}
              </button>
          </bem.FormModal__item>
        </bem.FormModal__form>

        { kind != 'collection' && asset_type == 'survey' &&
          <bem.FormView__cell>
            <bem.FormView__cell m='label'>
              {t('Select share settings')}
            </bem.FormView__cell>
            <PublicPermDiv
              uid={uid}
              publicPerm={this.state.public_permission}
              kind={kind}
              objectUrl={objectUrl}
            />
          </bem.FormView__cell>
        }
      </bem.FormModal>
    );
  }
});

export default SharingForm;
<commit_msg>fix sharing by link URL fixes #1293<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import Reflux from 'reflux';
import TagsInput from 'react-tagsinput';
import stores from '../stores';
import actions from '../actions';
import mixins from '../mixins';
import classNames from 'classnames';
import Select from 'react-select';
import bem from '../bem';
import {
  t,
  parsePermissions,
  getAnonymousUserPermission,
  stringToColor,
  anonUsername
} from '../utils';

var UserPermDiv = React.createClass({
  mixins: [
    mixins.permissions,
  ],
  PermOnChange(perm) {
    var cans = this.props.can;
    if (perm) {
      var permName = perm.value;
      this.setPerm(permName, this.props);
      if (permName == 'view' && cans.change)
        this.removePerm('change', cans.change, this.props.uid);
    } else {
      if (cans.view)
        this.removePerm('view', cans.view, this.props.uid);
      if (cans.change)
        this.removePerm('change', cans.change, this.props.uid);
    }

  },
  render () {
    var initialsStyle = {
      background: `#${stringToColor(this.props.username)}`
    };

    var currentPerm = '';
    var cans = this.props.can;

    if (cans.change) {
      var currentPerm = 'change';
    } else if (cans.view) {
      var currentPerm = 'view';
    }

    var availablePermissions = [
      {value: 'view', label: t('Can View')},
      {value: 'change', label: t('Can Edit')}
    ];

    return (
      <bem.UserRow m={cans.view || cans.change ? 'regular' : 'deleted'}>
        <bem.UserRow__avatar>
          <bem.AccountBox__initials style={initialsStyle}>
            {this.props.username.charAt(0)}
          </bem.AccountBox__initials>
        </bem.UserRow__avatar>
        <bem.UserRow__name>
          {this.props.username}
          {/*
<UserProfileLink username= />
*/}
        </bem.UserRow__name>
        <bem.UserRow__role>
          <Select
            name='userPerms'
            value={currentPerm}
            clearable={true}
            options={availablePermissions}
            onChange={this.PermOnChange}
          />
        </bem.UserRow__role>
      </bem.UserRow>
      );
  }
});

var PublicPermDiv = React.createClass({
  mixins: [
    mixins.permissions
  ],
  togglePerms() {
    if (this.props.publicPerm)
      this.removePerm('view',this.props.publicPerm, this.props.uid);
    else
      this.setPerm('view', {
          username: anonUsername,
          uid: this.props.uid,
          kind: this.props.kind,
          objectUrl: this.props.objectUrl
        }
      );
  },
  render () {
    var uid = this.props.uid;

    var href = `#/orms/${uid}`;
    var url = `${window.location.protocol}//${window.location.host}/${href}`;

    return (
      <bem.FormModal__item m='perms-link'>
        <input  type="checkbox"
                checked={this.props.publicPerm ? true : false}
                onChange={this.togglePerms}
                id="share-by-link"/>
        {t('Share by link')}
        { this.props.publicPerm &&
          <bem.FormModal__item m='shareable-link'>

              {t('Shareable link')}

            <input type="text" value={url} readOnly />
          </bem.FormModal__item>
        }
      </bem.FormModal__item>
    );
  }
});

var SharingForm = React.createClass({
  mixins: [
    mixins.permissions,
    mixins.contextRouter,
    Reflux.ListenerMixin
  ],
  assetChange (data) {
    var uid = this.props.uid || this.currentAssetID(),
      asset = data[uid];

    if (asset) {
      this.setState({
        asset: asset,
        permissions: asset.permissions,
        owner: asset.owner__username,
        pperms: parsePermissions(asset.owner__username, asset.permissions),
        public_permission: getAnonymousUserPermission(asset.permissions),
        related_users: stores.asset.relatedUsers[uid]
      });
    }
  },
  componentDidMount () {
    this.listenTo(stores.userExists, this.userExistsStoreChange);
    if (this.props.uid) {
      actions.resources.loadAsset({id: this.props.uid});
    }
    this.listenTo(stores.asset, this.assetChange);
  },
  userExistsStoreChange (checked, result) {
    var inpVal = this.usernameFieldValue();
    if (inpVal === result) {
      var newStatus = checked[result] ? 'success' : 'error';
      this.setState({
        userInputStatus: newStatus
      });
    }
  },
  usernameField () {
    return ReactDOM.findDOMNode(this.refs.usernameInput);
  },
  usernameFieldValue () {
    return this.usernameField().value;
  },
  usernameCheck (evt) {
    var username = evt.target.value;
    if (username && username.length > 1) {
      var result = stores.userExists.checkUsername(username);
      if (result === undefined) {
        actions.misc.checkUsername(username);
      } else {
        log(result ? 'success' : 'error');
        this.setState({
          userInputStatus: result ? 'success' : 'error'
        });
      }
    } else {
      this.setState({
        userInputStatus: false
      });
    }
  },
  getInitialState () {
    return {
      userInputStatus: false,
      permInput: 'view'
    };
  },
  addInitialUserPermission (evt) {
    evt.preventDefault();
    var username = this.usernameFieldValue();
    if (stores.userExists.checkUsername(username)) {
      actions.permissions.assignPerm({
        username: username,
        uid: this.state.asset.uid,
        kind: this.state.asset.kind,
        objectUrl: this.props.objectUrl,
        role: this.state.permInput
      });
      this.usernameField().value = '';
    }
  },
  updatePermInput(permName) {
    this.setState({
      permInput: permName.value
    });
  },
  render () {
    var inpStatus = this.state.userInputStatus;
    if (!this.state.pperms) {
      return (
          <bem.Loading>
            <bem.Loading__inner>

              {t('loading...')}
            </bem.Loading__inner>
          </bem.Loading>
        );
    }
    var _perms = this.state.pperms;
    var perms = this.state.related_users.map(function(username){
      var currentPerm = _perms.filter(function(p){
        return p.username === username;
      })[0];
      if (currentPerm) {
        return currentPerm;
      } else {
        return {
          username: username,
          can: {}
        };
      }
    });
    var btnKls = classNames('mdl-button','mdl-js-button', 'mdl-button--raised', inpStatus === 'success' ? 'mdl-button--colored' : 'mdl-button--disabled');

    var availablePermissions = [
      {value: 'view', label: t('Can View')},
      {value: 'change', label: t('Can Edit')}
    ];

    var uid = this.state.asset.uid;
    var kind = this.state.asset.kind;
    var asset_type = this.state.asset.asset_type;
    var objectUrl = this.state.asset.url;

    if (!perms) {
      return (

loading

        );
    }

    var initialsStyle = {
      background: `#${stringToColor(this.state.asset.owner__username)}`
    };

    return (
      <bem.FormModal>
        <bem.FormModal__item>
          <bem.FormView__cell m='label'>
            {t('Who has access')}
          </bem.FormView__cell>
          <bem.UserRow>
            <bem.UserRow__avatar>
              <bem.AccountBox__initials style={initialsStyle}>
                {this.state.asset.owner__username.charAt(0)}
              </bem.AccountBox__initials>
            </bem.UserRow__avatar>
            <bem.UserRow__name>

{this.state.asset.owner__username}

            </bem.UserRow__name>
            <bem.UserRow__role>{t('is owner')}</bem.UserRow__role>
          </bem.UserRow>

          {perms.map((perm)=> {
            return <UserPermDiv key={`perm.${uid}.${perm.username}`} ref={perm.username} uid={uid} kind={kind} objectUrl={objectUrl} {...perm} />;
          })}

        </bem.FormModal__item>

        <bem.FormModal__form onSubmit={this.addInitialUserPermission} className="sharing-form__user">
            <bem.FormView__cell m='label'>
              {t('Invite collaborators')}
            </bem.FormView__cell>
            <bem.FormModal__item m='perms-user'>
              <input type="text"
                  id="permsUser"
                  ref='usernameInput'
                  placeholder={t('Enter a username')}
                  onKeyUp={this.usernameCheck}
                  onChange={this.usernameCheck}
              />
              <Select
                  id='permGiven'
                  ref='permInput'
                  value={this.state.permInput}
                  clearable={false}
                  options={availablePermissions}
                  onChange={this.updatePermInput}
              />
              <button className={btnKls}>
                  {t('invite')}
              </button>
          </bem.FormModal__item>
        </bem.FormModal__form>

        { kind != 'collection' && asset_type == 'survey' &&
          <bem.FormView__cell>
            <bem.FormView__cell m='label'>
              {t('Select share settings')}
            </bem.FormView__cell>
            <PublicPermDiv
              uid={uid}
              publicPerm={this.state.public_permission}
              kind={kind}
              objectUrl={objectUrl}
            />
          </bem.FormView__cell>
        }
      </bem.FormModal>
    );
  }
});

export default SharingForm;
<|endoftext|>


<commit_before>/**
 * @fileOverview The line component.
 */

var Base = require('./base.comp');

/**
 * The line component.
 *
 * @constructor
 * @extends {app.level.component.Base}
 */
var Line = module.exports = Base.extend(function() {
  this.type = Base.Type.LINE;

  /** @type {?number} Pos x2 */
  this.x2 = null;
  /** @type {?number} Pos y2 */
  this.y2 = null;
});

/**
 * Draw the component on the underlying vector library.
 *
 * @param {number} x1 The x1 position.
 * @param {number} y1 The y1 position.
 * @param {number} x2 The x2 position.
 * @param {number} y2 The y2 position.
 */
Line.prototype.draw = function(x1, y1, x2, y2) {
  this.x1 = x1;
  this.y1 = y1;
  this.x2 = x2;
  this.y2 = y2;

  this.vector.two.makeLine(x1, y1, x2, y2);
};

/**
 * Get the position of the component.
 *
 * @return {Array} The type.
 */
Line.prototype.getPosition = function() {
  return [
    this.x1,
    this.y1,
    this.x2,
    this.y2,
  ];
};

<commit_msg>Use vector's makeline method<commit_after>/**
 * @fileOverview The line component.
 */

var Base = require('./base.comp');

/**
 * The line component.
 *
 * @constructor
 * @extends {app.level.component.Base}
 */
var Line = module.exports = Base.extend(function() {
  this.type = Base.Type.LINE;

  /** @type {?number} Pos x2 */
  this.x2 = null;
  /** @type {?number} Pos y2 */
  this.y2 = null;
});

/**
 * Draw the component on the underlying vector library.
 *
 * @param {number} x1 The x1 position.
 * @param {number} y1 The y1 position.
 * @param {number} x2 The x2 position.
 * @param {number} y2 The y2 position.
 */
Line.prototype.draw = function(x1, y1, x2, y2) {
  this.x1 = x1;
  this.y1 = y1;
  this.x2 = x2;
  this.y2 = y2;

  this.vector.makeLine(x1, y1, x2, y2);
};

/**
 * Get the position of the component.
 *
 * @return {Array} The type.
 */
Line.prototype.getPosition = function() {
  return [
    this.x1,
    this.y1,
    this.x2,
    this.y2,
  ];
};

<|endoftext|>


<commit_before>describe("About Mutability", function() {

  it("should expect object properties to be public and mutable", function () {
    var aPerson = {firstname: "John", lastname: "Smith" };
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe(FILL_ME_IN);
  });

  it("should understand that constructed properties are public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    var aPerson = new Person ("John", "Smith");
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe(FILL_ME_IN);
  });

  it("should expect prototype properties to be public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    Person.prototype.getFullName = function () {
      return this.firstname + " " + this.lastname;
    };

    var aPerson = new Person ("John", "Smith");
    expect(aPerson.getFullName()).toBe(FILL_ME_IN);

    aPerson.getFullName = function () {
      return this.lastname + ", " + this.firstname;
    };

    expect(aPerson.getFullName()).toBe(FILL_ME_IN);
  });

  it("should know that variables inside a constructor and constructor args are private", function () {
    function Person(firstname, lastname)
    {
      var fullName = firstname + " " + lastname;

      this.getFirstName = function () { return firstname; };
      this.getLastName = function () { return lastname; };
      this.getFullName = function () { return fullName; };
    }
    var aPerson = new Person ("John", "Smith");

    aPerson.firstname = "Penny";
    aPerson.lastname = "Andrews";
    aPerson.fullName = "Penny Andrews";

    expect(aPerson.getFirstName()).toBe(FILL_ME_IN);
    expect(aPerson.getLastName()).toBe(FILL_ME_IN);
    expect(aPerson.getFullName()).toBe(FILL_ME_IN);

    aPerson.getFullName = function () {
      return aPerson.lastname + ", " + aPerson.firstname;
    };

    expect(aPerson.getFullName()).toBe(FILL_ME_IN);
  });

});
<commit_msg>Completed About Mutability<commit_after>describe("About Mutability", function() {

  it("should expect object properties to be public and mutable", function () {
    var aPerson = {firstname: "John", lastname: "Smith" };
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe("Alan");
  });

  it("should understand that constructed properties are public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    var aPerson = new Person ("John", "Smith");
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe("Alan");
  });

  it("should expect prototype properties to be public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    Person.prototype.getFullName = function () {
      return this.firstname + " " + this.lastname;
    };

    var aPerson = new Person ("John", "Smith");
    expect(aPerson.getFullName()).toBe("John Smith");

    aPerson.getFullName = function () {
      return this.lastname + ", " + this.firstname;
    };

    expect(aPerson.getFullName()).toBe("Smith, John");
  });

  it("should know that variables inside a constructor and constructor args are private", function () {

    // **NB** come back to this part later

    function Person(firstname, lastname)
    {
      var fullName = firstname + " " + lastname;

      this.getFirstName = function () { return firstname; };
      this.getLastName = function () { return lastname; };
      this.getFullName = function () { return fullName; };
    }
    var aPerson = new Person ("John", "Smith");

    aPerson.firstname = "Penny";
    aPerson.lastname = "Andrews";
    aPerson.fullName = "Penny Andrews";

    expect(aPerson.getFirstName()).toBe("John");
    expect(aPerson.getLastName()).toBe("Smith");
    expect(aPerson.getFullName()).toBe("John Smith");

    aPerson.getFullName = function () {
      return aPerson.lastname + ", " + aPerson.firstname;
    };

    expect(aPerson.getFullName()).toBe("Andrews, Penny");
  });

});
<|endoftext|>


<commit_before>describe("About Mutability", function() {

  it("should expect object properties to be public and mutable", function () {
    var aPerson = {firstname: "John", lastname: "Smith" };
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe(FILL_ME_IN);
  });

  it("should understand that constructed properties are public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    var aPerson = new Person ("John", "Smith");
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe(FILL_ME_IN);
  });

  it("should expect prototype properties to be public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    Person.prototype.getFullName = function () {
      return this.firstname + " " + this.lastname;
    };

    var aPerson = new Person ("John", "Smith");
    expect(aPerson.getFullName()).toBe(FILL_ME_IN);

    aPerson.getFullName = function () {
      return this.lastname + ", " + this.firstname;
    };

    expect(aPerson.getFullName()).toBe(FILL_ME_IN);
  });

  it("should know that variables inside a constructor and constructor args are private", function () {
    function Person(firstname, lastname)
    {
      var fullName = firstname + " " + lastname;

      this.getFirstName = function () { return firstname; };
      this.getLastName = function () { return lastname; };
      this.getFullName = function () { return fullName; };
    }
    var aPerson = new Person ("John", "Smith");

    aPerson.firstname = "Penny";
    aPerson.lastname = "Andrews";
    aPerson.fullName = "Penny Andrews";

    expect(aPerson.getFirstName()).toBe(FILL_ME_IN);
    expect(aPerson.getLastName()).toBe(FILL_ME_IN);
    expect(aPerson.getFullName()).toBe(FILL_ME_IN);

    aPerson.getFullName = function () {
      return aPerson.lastname + ", " + aPerson.firstname;
    };

    expect(aPerson.getFullName()).toBe(FILL_ME_IN);
  });

});
<commit_msg>AboutMutability tests passing<commit_after>describe("About Mutability", function() {

  it("should expect object properties to be public and mutable", function () {
    var aPerson = {firstname: "John", lastname: "Smith" };
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe("Alan");
  });

  it("should understand that constructed properties are public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    var aPerson = new Person ("John", "Smith");
    aPerson.firstname = "Alan";

    expect(aPerson.firstname).toBe("Alan");
  });

  it("should expect prototype properties to be public and mutable", function () {
    function Person(firstname, lastname)
    {
      this.firstname = firstname;
      this.lastname = lastname;
    }
    Person.prototype.getFullName = function () {
      return this.firstname + " " + this.lastname;
    };

    var aPerson = new Person ("John", "Smith");
    expect(aPerson.getFullName()).toBe("John Smith");

    aPerson.getFullName = function () {
      return this.lastname + ", " + this.firstname;
    };

    expect(aPerson.getFullName()).toBe("Smith, John");
  });

  it("should know that variables inside a constructor and constructor args are private", function () {
    function Person(firstname, lastname)
    {
      var fullName = firstname + " " + lastname;

      this.getFirstName = function () { return firstname; };
      this.getLastName = function () { return lastname; };
      this.getFullName = function () { return fullName; };
    }
    var aPerson = new Person ("John", "Smith");

    aPerson.firstname = "Penny";
    aPerson.lastname = "Andrews";
    aPerson.fullName = "Penny Andrews";

    expect(aPerson.getFirstName()).toBe("John");
    expect(aPerson.getLastName()).toBe("Smith");
    expect(aPerson.getFullName()).toBe("John Smith");

    aPerson.getFullName = function () {
      return aPerson.lastname + ", " + aPerson.firstname;
    };

    expect(aPerson.getFullName()).toBe("Andrews, Penny");
  });

});
<|endoftext|>


<commit_before>
$(document).ready(function() {
     showTree(false);

});

function toggleSiblings(elm) {

    var buttonValue = $(elm).val() == 'true';

    if (buttonValue) {
        $(elm).text("Hide siblings");
        $(elm).val(false);
    }
    else {
        $(elm).text("Show siblings");
        $(elm).val(true);

    }
    showTree(buttonValue)
    console.log(buttonValue);

}

function showTree(siblings) {

    $( "div[data-olswidget='tree']").empty();

    $( "div[data-olswidget='tree']" ).each(function() {

        // get param
        var ontologyName = $(this).data("olsontology");
        var termType = getUrlType($(this).data("ols-termtype"));
        var termIri = $(this).data("ols-iri");
        var relativePath = $(this).data("selectpath") ? $(this).data("selectpath") : '';

        console.log("Init tree for: " + ontologyName + " - " + termIri + " - " + termType);
        // show errors if above not defined

        // build tree
        $.jstree.defaults.core.data = true;
        $.jstree.defaults.core.expand_selected_onload = true;

        var rootUrl = relativePath + '/api/ontologies/' + ontologyName + '/' + termType + '/roots?size=1000';

        var baseUrl = relativePath + '/api/ontologies/' + ontologyName + '/' + termType + '/';
        var url = baseUrl + encodeURIComponent(encodeURIComponent(termIri)) + '/jstree' ;
        if (siblings) {
            url += '?siblings=true';
            console.log("rebuild tree iwth siblings " + url)
        }
        console.log("tree url " + url)
        var treeDiv = $('

')
            .jstree({
                'core' : {
                    'data': function (node, cb) {
                        console.log("node id: " + node.id + " term " + termIri);

                        if (node.id === '#' && termIri != '') {
                            $.getJSON(url, function (data) {
                                cb(data)
                            });
                        }
                        else if (node.id === '#' && termIri === '') {

                            // show roots
                            $.getJSON(rootUrl, function (data) {
                                var data = _processOlsData(data, '#', termType);
                                cb(data)
                            });
                        }
                        else {
                            var requestIri = node.original.iri;
                            // get all children
                            var childUrl = baseUrl + encodeURIComponent(encodeURIComponent(requestIri)) + '/jstree/children/'+ node.id;

                            $.getJSON(childUrl, function (data) {
                                //var parentId = node.id;
                                //var data = _processOlsData(data, parentId, termType);
                                cb(data)

                            });
                        }

                    },
                    "themes": {
                        "dots": true
                        , "icons": false,
                        "name" : "proton"
                        //"responsive" : true
                    }
                },
                plugins: ["sort"]
            }).bind("select_node.jstree", function (node, selected, event) {

                //var tree = $(this).jstree();
                //node = tree.get_node(event.target);
                //console.log(node);
                //console.log(selected);
                //console.log(event);
                // Do my action

                var type = termType;
                if (type == 'individual' && termIri != selected.node.original.iri) {
                    type = getUrlType('terms');
                }
                window.location.href = relativePath + "ontologies/" + selected.node.original.ontology_name + "/" + type + '?iri=' + encodeURIComponent(selected.node.original.iri);
            });

        $(this).append(treeDiv);

    });
}

function _processOlsData (data, parentId, termType) {

    var newData = [];
    var counter = 1;

    var results;
    if (termType == "properties") {
        console.log("getting term type:" + termType);
        results = data._embedded.properties;
    }
    else if (termType == "individuals") {
        results = data._embedded.individuals;
    }
    else {
        results = data._embedded.terms;
    }
    $.each(results, function(index, term) {
        var id = parentId + "_" + counter;
        var parent = parentId;
        if (parentId === '#') {
            id = counter;
            parent = parentId;
        }

        newData.push(
            {
                "id" : id,
                "parent" : parent,
                "iri" : term.iri,
                "ontology_name" : term.ontology_name,
                "text" : term.label,
                "leaf" : !term.has_children,
                "children" : term.has_children
            }
        );
        counter++;
    });
    return newData;

}<commit_msg>fixed tree linking<commit_after>
$(document).ready(function() {
     showTree(false);

});

function toggleSiblings(elm) {

    var buttonValue = $(elm).val() == 'true';

    if (buttonValue) {
        $(elm).text("Hide siblings");
        $(elm).val(false);
    }
    else {
        $(elm).text("Show siblings");
        $(elm).val(true);

    }
    showTree(buttonValue)
    console.log(buttonValue);

}

function showTree(siblings) {

    $( "div[data-olswidget='tree']").empty();

    $( "div[data-olswidget='tree']" ).each(function() {

        // get param
        var ontologyName = $(this).data("olsontology");
        var termType = getUrlType($(this).data("ols-termtype"));
        var termIri = $(this).data("ols-iri");
        var relativePath = $(this).data("selectpath") ? $(this).data("selectpath") : '';

        console.log("Init tree for: " + ontologyName + " - " + termIri + " - " + termType);
        // show errors if above not defined

        // build tree
        $.jstree.defaults.core.data = true;
        $.jstree.defaults.core.expand_selected_onload = true;

        var rootUrl = relativePath + '/api/ontologies/' + ontologyName + '/' + termType + '/roots?size=1000';

        var baseUrl = relativePath + '/api/ontologies/' + ontologyName + '/' + termType + '/';
        var url = baseUrl + encodeURIComponent(encodeURIComponent(termIri)) + '/jstree' ;
        if (siblings) {
            url += '?siblings=true';
            console.log("rebuild tree iwth siblings " + url)
        }
        console.log("tree url " + url)
        var treeDiv = $('

')
            .jstree({
                'core' : {
                    'data': function (node, cb) {
                        console.log("node id: " + node.id + " term " + termIri);

                        if (node.id === '#' && termIri != '') {
                            $.getJSON(url, function (data) {
                                cb(data)
                            });
                        }
                        else if (node.id === '#' && termIri === '') {

                            // show roots
                            $.getJSON(rootUrl, function (data) {
                                var data = _processOlsData(data, '#', termType);
                                cb(data)
                            });
                        }
                        else {
                            var requestIri = node.original.iri;
                            // get all children
                            var childUrl = baseUrl + encodeURIComponent(encodeURIComponent(requestIri)) + '/jstree/children/'+ node.id;

                            $.getJSON(childUrl, function (data) {
                                //var parentId = node.id;
                                //var data = _processOlsData(data, parentId, termType);
                                cb(data)

                            });
                        }

                    },
                    "themes": {
                        "dots": true
                        , "icons": false,
                        "name" : "proton"
                        //"responsive" : true
                    }
                },
                plugins: ["sort"]
            }).bind("select_node.jstree", function (node, selected, event) {

                //var tree = $(this).jstree();
                //node = tree.get_node(event.target);
                //console.log(node);
                //console.log(selected);
                //console.log(event);
                // Do my action

                var type = termType;
                if (type == 'individuals' && termIri != selected.node.original.iri) {
                    type = getUrlType('terms');
                }
                window.location.href = relativePath + "ontologies/" + selected.node.original.ontology_name + "/" + type + '?iri=' + encodeURIComponent(selected.node.original.iri);
            });

        $(this).append(treeDiv);

    });
}

function _processOlsData (data, parentId, termType) {

    var newData = [];
    var counter = 1;

    var results;
    if (termType == "properties") {
        console.log("getting term type:" + termType);
        results = data._embedded.properties;
    }
    else if (termType == "individuals") {
        results = data._embedded.individuals;
    }
    else {
        results = data._embedded.terms;
    }
    $.each(results, function(index, term) {
        var id = parentId + "_" + counter;
        var parent = parentId;
        if (parentId === '#') {
            id = counter;
            parent = parentId;
        }

        newData.push(
            {
                "id" : id,
                "parent" : parent,
                "iri" : term.iri,
                "ontology_name" : term.ontology_name,
                "text" : term.label,
                "leaf" : !term.has_children,
                "children" : term.has_children
            }
        );
        counter++;
    });
    return newData;

}<|endoftext|>


<commit_before>javascript:
(function() {

    if (mw.config.get('wgCanonicalSpecialPageName') !== 'Log' || mw.config.get('wgPageName').replace(/^Special:[^/]+\//, '') !== 'move') {
        return;
    }

    mw.loader.using(['mediawiki.util']).done(function() {

        $('li.mw-logline-move>a.new').each(function(_, e) {
            $(document.createTextNode(")")).insertAfter(e);
            var url = mw.config.get('wgScript') + '?' + $.param({
                title: 'Special:WhatLinksHere',
                target: mw.util.getParamValue('title', e.href),
            })
            $('連入').insertAfter(e);
            $(document.createTextNode(" (")).insertAfter(e);
        });

    });

}
)();
<commit_msg>log-move-whatlinkshere: Enable on all logs<commit_after>javascript:
(function() {

    if (mw.config.get('wgCanonicalSpecialPageName') !== 'Log') {
        return;
    }

    mw.loader.using(['mediawiki.util']).done(function() {

        $('li.mw-logline-move>a.new').each(function(_, e) {
            $(document.createTextNode(")")).insertAfter(e);
            var url = mw.config.get('wgScript') + '?' + $.param({
                title: 'Special:WhatLinksHere',
                target: mw.util.getParamValue('title', e.href),
            })
            $('連入').insertAfter(e);
            $(document.createTextNode(" (")).insertAfter(e);
        });

    });

}
)();
<|endoftext|>


<commit_before>'use strict';

(function (angular) {
  angular
    .module('eventsManualPluginContent')
      .controller('ContentHomeCtrl', ['$scope', 'TAG_NAMES', 'STATUS_CODE', 'DataStore', 'LAYOUTS', '$sce', 'PAGINATION', 'Buildfire', '$modal',
        function ($scope, TAG_NAMES, STATUS_CODE, DataStore, LAYOUTS, $sce, PAGINATION, Buildfire, $modal) {
          var _data = {
          "content": {},
          "design": {
            "itemDetailsLayout": LAYOUTS.itemDetailLayouts[0].name,
            "itemDetailsBgImage": ""
          }
        };
          var searchOptions = {
            skip: 0,
            limit: PAGINATION.eventsCount, // the plus one is to check if there are any more
            sort:{"startDate":1 }
          };
        var ContentHome = this;
        ContentHome.searchEvent = null;
        /*
         * ContentHome.events used to store the list of events fetched from datastore.
         */
        ContentHome.events = {};
        ContentHome.busy = false;

        /*
         * ContentHome.data used to store EventsInfo which from datastore.
         */
        ContentHome.masterData = null;
        ContentHome.data = angular.copy(_data);

        function updateMasterItem(data) {
          ContentHome.masterData = angular.copy(data);
        }

        function isUnchanged(data) {
          return angular.equals(data, ContentHome.masterData);
        }

        /*
         * Go pull any previously saved data
         * */
        var init = function () {
          var success = function (result) {
              console.info('Init success result:', result);
              ContentHome.data = result.data;
              if (ContentHome.data) {
                if (!ContentHome.data.content)
                  ContentHome.data.content = {};
                updateMasterItem(ContentHome.data);
              }
              if (tmrDelay)clearTimeout(tmrDelay);
            }
            , error = function (err) {
              if (err && err.code !== STATUS_CODE.NOT_FOUND) {
                console.error('Error while getting data', err);
                if (tmrDelay)clearTimeout(tmrDelay);
              }
              else if (err && err.code === STATUS_CODE.NOT_FOUND) {
                saveData(JSON.parse(angular.toJson(ContentHome.data)), TAG_NAMES.EVENTS_MANUAL_INFO);
              }
            };

          DataStore.get(TAG_NAMES.EVENTS_MANUAL_INFO).then(success, error);
          };
        init();
        ContentHome.safeHtml = function (html) {
          if (html)
            return $sce.trustAsHtml(html);
        };
        ContentHome.searchEvents = function(search)
        {
          if (search) {
            var regex = "\\b" + search + "\\b";
            searchOptions.filter = {"$or": [{"data.title": {"$regex": regex, "$options": "i"}}]};
            }
           else {
            searchOptions.filter = {"data.title": {"$regex": '/*'}};
          }

          var successEvents = function (result) {
            Buildfire.spinner.hide();
            ContentHome.events = result;
          }, errorEvents = function (err) {
            Buildfire.spinner.hide();
            console.log("Error searching events:" +err)
          };
          DataStore.search(searchOptions, TAG_NAMES.EVENTS_MANUAL).then(successEvents, errorEvents);
        };

        ContentHome.removeEvent = function (eventId, index) {
          var status = function (result) {
              console.log(result)
            },
            err = function (err) {
              console.log(err)
            }
          var modalInstance = $modal.open({
            templateUrl: 'templates/modals/remove-event.html',
            controller: 'RemoveEventPopupCtrl',
            controllerAs: 'RemoveEventPopup',
            size: 'sm',
            resolve: {
              eventsManualData: function () {
              return ContentHome.events[index];
              }
            }
          });
          modalInstance.result.then(function (message) {
            if (message === 'yes') {
              ContentHome.events.splice(index, 1);
              DataStore.deleteById(eventId, TAG_NAMES.EVENTS_MANUAL).then(status, err)
            }
          }, function (data) {
            //do something on cancel
          });
        };
        /*
         * Call the datastore to save the data object
         */
        var saveData = function (newObj, tag) {
          if (typeof newObj === 'undefined') {
            return;
          }
          var success = function (result) {
              console.info('Saved data result: ', result);
              updateMasterItem(newObj);
            }
            , error = function (err) {
              console.error('Error while saving data : ', err);
            };
          DataStore.save(newObj, tag).then(success, error);
        };

        /*
         * create an artificial delay so api isnt called on every character entered
         * */
        var tmrDelay = null;
        var saveDataWithDelay = function (newObj) {
          if (newObj) {
            if (isUnchanged(newObj)) {
              return;
            }
            if (tmrDelay) {
              clearTimeout(tmrDelay);
            }
            tmrDelay = setTimeout(function () {
              saveData(JSON.parse(angular.toJson(newObj)), TAG_NAMES.EVENTS_MANUAL_INFO);
            }, 500);
          }
        };
        /*
         * watch for changes in data and trigger the saveDataWithDelay function on change
         * */

        $scope.$watch(function () {
          return ContentHome.data;
        }, saveDataWithDelay, true);

          var getManualEvents = function () {
            //  Buildfire.spinner.show();
            var successEvents = function (result) {
              //Buildfire.spinner.hide();
              //console.log("length",ContentHome.events.length)
              ContentHome.events = ContentHome.events.length ? ContentHome.events.concat(result) : result;
              searchOptions.skip = searchOptions.skip + PAGINATION.eventsCount;
              console.log("result",ContentHome.events)
              if (result.length == PAGINATION.eventsCount) {
                ContentHome.busy = false;
              }

            }, errorEvents = function () {
              //  Buildfire.spinner.hide();
              console.log("Error fetching events");
            };

            DataStore.search(searchOptions, TAG_NAMES.EVENTS_MANUAL).then(successEvents, errorEvents);
          };
          ContentHome.loadMore = function () {
            console.log("end page",ContentHome.busy)
           if (ContentHome.busy) return;
            ContentHome.busy = true;
            getManualEvents();
          };
      }]);
})(window.angular);
<commit_msg>Modified content home search with lazy loading.<commit_after>'use strict';

(function (angular) {
  angular
    .module('eventsManualPluginContent')
      .controller('ContentHomeCtrl', ['$scope', 'TAG_NAMES', 'STATUS_CODE', 'DataStore', 'LAYOUTS', '$sce', 'PAGINATION', 'Buildfire', '$modal',
        function ($scope, TAG_NAMES, STATUS_CODE, DataStore, LAYOUTS, $sce, PAGINATION, Buildfire, $modal) {
          var _data = {
          "content": {},
          "design": {
            "itemDetailsLayout": LAYOUTS.itemDetailLayouts[0].name,
            "itemDetailsBgImage": ""
          }
        };
          var searchOptions = {
            skip: 0,
            limit: PAGINATION.eventsCount, // the plus one is to check if there are any more
            sort:{"startDate":1 },
          };
        var regex;
        var ContentHome = this;
        ContentHome.searchEvent = null;
        /*
         * ContentHome.events used to store the list of events fetched from datastore.
         */
        ContentHome.events = {};
        ContentHome.busy = false;

        /*
         * ContentHome.data used to store EventsInfo which from datastore.
         */
        ContentHome.masterData = null;
        ContentHome.data = angular.copy(_data);

        function updateMasterItem(data) {
          ContentHome.masterData = angular.copy(data);
        }

        function isUnchanged(data) {
          return angular.equals(data, ContentHome.masterData);
        }

        /*
         * Go pull any previously saved data
         * */
        var init = function () {
          var success = function (result) {
              console.info('Init success result:', result);
              ContentHome.data = result.data;
              if (ContentHome.data) {
                if (!ContentHome.data.content)
                  ContentHome.data.content = {};
                updateMasterItem(ContentHome.data);
              }
              if (tmrDelay)clearTimeout(tmrDelay);
            }
            , error = function (err) {
              if (err && err.code !== STATUS_CODE.NOT_FOUND) {
                console.error('Error while getting data', err);
                if (tmrDelay)clearTimeout(tmrDelay);
              }
              else if (err && err.code === STATUS_CODE.NOT_FOUND) {
                saveData(JSON.parse(angular.toJson(ContentHome.data)), TAG_NAMES.EVENTS_MANUAL_INFO);
              }
            };
          DataStore.get(TAG_NAMES.EVENTS_MANUAL_INFO).then(success, error);
          };
        init();
        ContentHome.safeHtml = function (html) {
          if (html)
            return $sce.trustAsHtml(html);
        };
        ContentHome.searchEvents = function(search)
        {
          ContentHome.events =[];
          ContentHome.busy = false;
          searchOptions.skip =0;
          if (search) {
            regex = "\\b" + search + "\\b";
            searchOptions.filter = {"$or": [{"data.title": {"$regex": regex, "$options": "i"}}]};
            }
           else {
            searchOptions.filter = {"data.title": {"$regex": '/*'}};
          }
          ContentHome.loadMore();
        };

        ContentHome.removeEvent = function (eventId, index) {
          var status = function (result) {
              console.log(result)
            },
            err = function (err) {
              console.log(err)
            }
          var modalInstance = $modal.open({
            templateUrl: 'templates/modals/remove-event.html',
            controller: 'RemoveEventPopupCtrl',
            controllerAs: 'RemoveEventPopup',
            size: 'sm',
            resolve: {
              eventsManualData: function () {
              return ContentHome.events[index];
              }
            }
          });
          modalInstance.result.then(function (message) {
            if (message === 'yes') {
              ContentHome.events.splice(index, 1);
              DataStore.deleteById(eventId, TAG_NAMES.EVENTS_MANUAL).then(status, err)
            }
          }, function (data) {
            //do something on cancel
          });
        };
        /*
         * Call the datastore to save the data object
         */
        var saveData = function (newObj, tag) {
          if (typeof newObj === 'undefined') {
            return;
          }
          var success = function (result) {
              console.info('Saved data result: ', result);
              updateMasterItem(newObj);
            }
            , error = function (err) {
              console.error('Error while saving data : ', err);
            };
          DataStore.save(newObj, tag).then(success, error);
        };

        /*
         * create an artificial delay so api isnt called on every character entered
         * */
        var tmrDelay = null;
        var saveDataWithDelay = function (newObj) {
          if (newObj) {
            if (isUnchanged(newObj)) {
              return;
            }
            if (tmrDelay) {
              clearTimeout(tmrDelay);
            }
            tmrDelay = setTimeout(function () {
              saveData(JSON.parse(angular.toJson(newObj)), TAG_NAMES.EVENTS_MANUAL_INFO);
            }, 500);
          }
        };
        /*
         * watch for changes in data and trigger the saveDataWithDelay function on change
         * */

        $scope.$watch(function () {
          return ContentHome.data;
        }, saveDataWithDelay, true);

          var getManualEvents = function () {
              Buildfire.spinner.show();
            var successEvents = function (result) {
              Buildfire.spinner.hide();
              ContentHome.events = ContentHome.events.length ? ContentHome.events.concat(result) : result;
              searchOptions.skip = searchOptions.skip + PAGINATION.eventsCount;
              if (result.length == PAGINATION.eventsCount) {
                ContentHome.busy = false;
              }
            }, errorEvents = function () {
                Buildfire.spinner.hide();
              console.log("Error fetching events");
            };
            DataStore.search(searchOptions, TAG_NAMES.EVENTS_MANUAL).then(successEvents, errorEvents);
          };
          ContentHome.loadMore = function () {
            if (ContentHome.busy) return;
            ContentHome.busy = true;
            getManualEvents();
          };
      }]);
})(window.angular);
<|endoftext|>


<commit_before>'use strict';
(function (angular, buildfire) {
  angular
    .module('seminarNotesPluginContent')
    .controller('ContentItemCtrl', ['$scope', '$routeParams', 'Buildfire', 'DataStore', 'TAG_NAMES', '$location', '$timeout', 'RankOfLastItem',
      function ($scope, $routeParams, Buildfire, DataStore, TAG_NAMES, $location, $timeout, RankOfLastItem) {
        var ContentItem = this;
        var _rankOfLastItem = RankOfLastItem.getRank();
        var _data = {
          "title": "",
          "deepLinkUrl": "",
          "summary": "",
          "listImage": "",
          "dateCreated": "",
          "publishDate": "",
          "links": [],
          "description": "",
          "carouselImages": [],
          "rank": _rankOfLastItem,
          "itemListBgImage": ""
        };

        var editor, listImage, background = "";

        ContentItem.item = {
          data: angular.copy(_data)
        };

        ContentItem.isUpdating = false;
        ContentItem.isNewItemInserted = false;
        ContentItem.unchangedData = true;

        ContentItem.isValidItem = function (item) {
          return item.title;
        };

        ContentItem.descriptionWYSIWYGOptions = {
          plugins: 'advlist autolink link lists charmap print preview',
          skin: 'lightgray',
          trusted: true,
          theme: 'modern'
        };

        /*
         Send message to widget that this page has been opened
         */
        if ($routeParams.id) {
          buildfire.messaging.sendMessageToWidget({
            id: $routeParams.id,
            type: 'OpenItem'
          });
        }

        $scope.$on('$viewContentLoaded', function () {
          $timeout(function () {
            // create a new instance of the buildfire carousel editor
            editor = new Buildfire.components.carousel.editor("#carousel2");
            console.log(editor);

            // this method will be called when a new item added to the list
            editor.onAddItems = function (items) {
              if (!ContentItem.item.data.carouselImages)
                ContentItem.item.data.carouselImages = [];
              ContentItem.item.data.carouselImages.push.apply(ContentItem.item.data.carouselImages, items);
              $scope.$digest();
            };
            // this method will be called when an item deleted from the list
            editor.onDeleteItem = function (item, index) {
              ContentItem.item.data.carouselImages.splice(index, 1);
              $scope.$digest();
            };
            // this method will be called when you edit item details
            editor.onItemChange = function (item, index) {
              ContentItem.item.data.carouselImages.splice(index, 1, item);
              $scope.$digest();
            };
            // this method will be called when you change the order of items
            editor.onOrderChange = function (item, oldIndex, newIndex) {
              var items = ContentItem.item.data.carouselImages,
                tmp = items[oldIndex],
                i;

              if (oldIndex < newIndex) {
                for (i = oldIndex + 1; i <= newIndex; i++) {
                  items[i - 1] = items[i];
                }
              } else {
                for (i = oldIndex - 1; i >= newIndex; i--) {
                  items[i + 1] = items[i];
                }
              }
              items[newIndex] = tmp;

              ContentItem.item.data.carouselImages = items;
              $scope.$digest();
            };

            /* Build fire thumbnail component to add thumbnail image*/
            listImage = new Buildfire.components.images.thumbnail("#listImage", {
              title: "List Image",
              dimensionsLabel: "600x280"
            });

            listImage.onChange = function (url) {
              ContentItem.item.data.listImage = url;
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            listImage.onDelete = function (url) {
              ContentItem.item.data.listImage = "";
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            /* background image add <start>*/
            background = new Buildfire.components.images.thumbnail("#background");

            background.onChange = function (url) {
              ContentItem.item.data.itemListBgImage = url;
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            background.onDelete = function (url) {
              ContentItem.item.data.itemListBgImage = "";
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            if ($routeParams.id) {
              ContentItem.getItem($routeParams.id);
            }

          }, 0);
        });

        /**
         * link and sortable options
         */
        var linkOptions = {"icon": "true"};

        ContentItem.linksSortableOptions = {
          handle: '> .cursor-grab'
        };

        var updateMasterItem = function (item) {
          ContentItem.masterItem = angular.copy(item);
        };

        var isUnchanged = function (item) {
          return angular.equals(item, ContentItem.masterItem);
        };

        ContentItem.addNewItem = function () {
          ContentItem.isNewItemInserted = true;
          _rankOfLastItem = _rankOfLastItem + 10;
          ContentItem.item.data.dateCreated = +new Date();
          ContentItem.item.data.rank = _rankOfLastItem;
          localStorage.setItem('pluginLoadedFirst', true);

          var successItem = function (result) {
            console.log("Inserted", result.id);
            ContentItem.isUpdating = false;
            ContentItem.item.id = result.id;
            _data.dateCreated = ContentItem.item.data.dateCreated;
            _data.rank = ContentItem.item.data.rank;
            RankOfLastItem.setRank(_rankOfLastItem);
            updateMasterItem(ContentItem.item);
            ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: result.id});
            if (ContentItem.item.id) {
              buildfire.messaging.sendMessageToWidget({
                id: ContentItem.item.id,
                type: 'AddNewItem'
              });
            }
          }, errorItem = function () {
            ContentItem.isNewItemInserted = false;
            return console.error('There was a problem saving your data');
          };
          DataStore.insert(ContentItem.item.data, TAG_NAMES.SEMINAR_ITEMS).then(successItem, errorItem);
        };

        ContentItem.updateItemData = function () {
          DataStore.update(ContentItem.item.id, ContentItem.item.data, TAG_NAMES.SEMINAR_ITEMS, function (err) {
            ContentItem.isUpdating = false;
            if (err)
              return console.error('There was a problem saving your data');
          })
        };

        ContentItem.getItem = function (id) {
          var successItem = function (result) {
            ContentItem.item = result;
            Buildfire.spinner.hide();
            if (ContentItem.item.data.listImage) {
              listImage.loadbackground(ContentItem.item.data.listImage);
            }
            if (!ContentItem.item.data.carouselImages)
              editor.loadItems([]);
            else
              editor.loadItems(ContentItem.item.data.carouselImages);
            if (ContentItem.item.data.itemListBgImage) {
              background.loadbackground(ContentItem.item.data.itemListBgImage);
            }
            _data.dateCreated = result.data.dateCreated;
            _data.rank = result.data.rank;
            if(result && result.data && !result.data.deepLinkUrl) {
              ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: result.id});
            }
            updateMasterItem(ContentItem.item);
          }, errorItem = function () {
            Buildfire.spinner.hide();
            throw console.error('There was a problem fetching your data', err);
          };
          Buildfire.spinner.show();
          DataStore.getById(id, TAG_NAMES.SEMINAR_ITEMS).then(successItem, errorItem);
        };

        /**
         * Add dynamic link
         */

        ContentItem.addLink = function () {
          var options = {showIcons: false};
          var callback = function (error, result) {
            if (error) {
              return console.error('Error:', error);
            }
            if (!ContentItem.item.data.links)
              ContentItem.item.data.links = [];
            if (result.title)
              ContentItem.item.data.links.push(result);
            $scope.$digest();
          };
          Buildfire.actionItems.showDialog(null, options, callback);
        };

        /**
         * Remove dynamic link
         */

        ContentItem.removeLink = function (index) {
          if (ContentItem.item.data && ContentItem.item.data.links) {
            ContentItem.item.data.links.splice(index, 1);
          }
        };

        /**
         * Edit dynamic link
         */

        ContentItem.editLink = function (link, index) {
          Buildfire.actionItems.showDialog(link, linkOptions, function editLinkCallback(error, result) {
            if (error) {
              return console.error('Error:', error);
            }
            if (!ContentItem.item.data.links) {
              ContentItem.item.data.links = [];
            }
            if (result === null) {
              return console.error('Error:Can not save data, Null record found.');
            }
            ContentItem.item.data.links.splice(index, 1, result);
            $scope.$digest();
          });
        };

        ContentItem.goToHome = function () {
            buildfire.messaging.sendMessageToWidget({});
          $location.path('#/');
        };

        var tmrDelayForItem = null;

        var updateItemsWithDelay = function (item) {
          clearTimeout(tmrDelayForItem);
          ContentItem.isUpdating = false;
          ContentItem.unchangedData = angular.equals(_data, ContentItem.item.data);

          ContentItem.isItemValid = ContentItem.isValidItem(ContentItem.item.data);
          if (!ContentItem.isUpdating && !isUnchanged(ContentItem.item) && ContentItem.isItemValid) {
            tmrDelayForItem = setTimeout(function () {
              if (item.id) {
                ContentItem.updateItemData();
              } else if (!ContentItem.isNewItemInserted) {
                ContentItem.addNewItem();
              }
            }, 300);
          }
        };

        $scope.$watch(function () {
          return ContentItem.item;
        }, updateItemsWithDelay, true);

      }]);
})(window.angular, window.buildfire);<commit_msg>changed the dimension text to 1200x675 as suggested by nathan for list image<commit_after>'use strict';
(function (angular, buildfire) {
  angular
    .module('seminarNotesPluginContent')
    .controller('ContentItemCtrl', ['$scope', '$routeParams', 'Buildfire', 'DataStore', 'TAG_NAMES', '$location', '$timeout', 'RankOfLastItem',
      function ($scope, $routeParams, Buildfire, DataStore, TAG_NAMES, $location, $timeout, RankOfLastItem) {
        var ContentItem = this;
        var _rankOfLastItem = RankOfLastItem.getRank();
        var _data = {
          "title": "",
          "deepLinkUrl": "",
          "summary": "",
          "listImage": "",
          "dateCreated": "",
          "publishDate": "",
          "links": [],
          "description": "",
          "carouselImages": [],
          "rank": _rankOfLastItem,
          "itemListBgImage": ""
        };

        var editor, listImage, background = "";

        ContentItem.item = {
          data: angular.copy(_data)
        };

        ContentItem.isUpdating = false;
        ContentItem.isNewItemInserted = false;
        ContentItem.unchangedData = true;

        ContentItem.isValidItem = function (item) {
          return item.title;
        };

        ContentItem.descriptionWYSIWYGOptions = {
          plugins: 'advlist autolink link lists charmap print preview',
          skin: 'lightgray',
          trusted: true,
          theme: 'modern'
        };

        /*
         Send message to widget that this page has been opened
         */
        if ($routeParams.id) {
          buildfire.messaging.sendMessageToWidget({
            id: $routeParams.id,
            type: 'OpenItem'
          });
        }

        $scope.$on('$viewContentLoaded', function () {
          $timeout(function () {
            // create a new instance of the buildfire carousel editor
            editor = new Buildfire.components.carousel.editor("#carousel2");
            console.log(editor);

            // this method will be called when a new item added to the list
            editor.onAddItems = function (items) {
              if (!ContentItem.item.data.carouselImages)
                ContentItem.item.data.carouselImages = [];
              ContentItem.item.data.carouselImages.push.apply(ContentItem.item.data.carouselImages, items);
              $scope.$digest();
            };
            // this method will be called when an item deleted from the list
            editor.onDeleteItem = function (item, index) {
              ContentItem.item.data.carouselImages.splice(index, 1);
              $scope.$digest();
            };
            // this method will be called when you edit item details
            editor.onItemChange = function (item, index) {
              ContentItem.item.data.carouselImages.splice(index, 1, item);
              $scope.$digest();
            };
            // this method will be called when you change the order of items
            editor.onOrderChange = function (item, oldIndex, newIndex) {
              var items = ContentItem.item.data.carouselImages,
                tmp = items[oldIndex],
                i;

              if (oldIndex < newIndex) {
                for (i = oldIndex + 1; i <= newIndex; i++) {
                  items[i - 1] = items[i];
                }
              } else {
                for (i = oldIndex - 1; i >= newIndex; i--) {
                  items[i + 1] = items[i];
                }
              }
              items[newIndex] = tmp;

              ContentItem.item.data.carouselImages = items;
              $scope.$digest();
            };

            /* Build fire thumbnail component to add thumbnail image*/
            listImage = new Buildfire.components.images.thumbnail("#listImage", {
              title: "List Image",
              dimensionsLabel: "1200x675"
            });

            listImage.onChange = function (url) {
              ContentItem.item.data.listImage = url;
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            listImage.onDelete = function (url) {
              ContentItem.item.data.listImage = "";
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            /* background image add <start>*/
            background = new Buildfire.components.images.thumbnail("#background");

            background.onChange = function (url) {
              ContentItem.item.data.itemListBgImage = url;
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            background.onDelete = function (url) {
              ContentItem.item.data.itemListBgImage = "";
              if (!$scope.$$phase && !$scope.$root.$$phase) {
                $scope.$apply();
              }
            };

            if ($routeParams.id) {
              ContentItem.getItem($routeParams.id);
            }

          }, 0);
        });

        /**
         * link and sortable options
         */
        var linkOptions = {"icon": "true"};

        ContentItem.linksSortableOptions = {
          handle: '> .cursor-grab'
        };

        var updateMasterItem = function (item) {
          ContentItem.masterItem = angular.copy(item);
        };

        var isUnchanged = function (item) {
          return angular.equals(item, ContentItem.masterItem);
        };

        ContentItem.addNewItem = function () {
          ContentItem.isNewItemInserted = true;
          _rankOfLastItem = _rankOfLastItem + 10;
          ContentItem.item.data.dateCreated = +new Date();
          ContentItem.item.data.rank = _rankOfLastItem;
          localStorage.setItem('pluginLoadedFirst', true);

          var successItem = function (result) {
            console.log("Inserted", result.id);
            ContentItem.isUpdating = false;
            ContentItem.item.id = result.id;
            _data.dateCreated = ContentItem.item.data.dateCreated;
            _data.rank = ContentItem.item.data.rank;
            RankOfLastItem.setRank(_rankOfLastItem);
            updateMasterItem(ContentItem.item);
            ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: result.id});
            if (ContentItem.item.id) {
              buildfire.messaging.sendMessageToWidget({
                id: ContentItem.item.id,
                type: 'AddNewItem'
              });
            }
          }, errorItem = function () {
            ContentItem.isNewItemInserted = false;
            return console.error('There was a problem saving your data');
          };
          DataStore.insert(ContentItem.item.data, TAG_NAMES.SEMINAR_ITEMS).then(successItem, errorItem);
        };

        ContentItem.updateItemData = function () {
          DataStore.update(ContentItem.item.id, ContentItem.item.data, TAG_NAMES.SEMINAR_ITEMS, function (err) {
            ContentItem.isUpdating = false;
            if (err)
              return console.error('There was a problem saving your data');
          })
        };

        ContentItem.getItem = function (id) {
          var successItem = function (result) {
            ContentItem.item = result;
            Buildfire.spinner.hide();
            if (ContentItem.item.data.listImage) {
              listImage.loadbackground(ContentItem.item.data.listImage);
            }
            if (!ContentItem.item.data.carouselImages)
              editor.loadItems([]);
            else
              editor.loadItems(ContentItem.item.data.carouselImages);
            if (ContentItem.item.data.itemListBgImage) {
              background.loadbackground(ContentItem.item.data.itemListBgImage);
            }
            _data.dateCreated = result.data.dateCreated;
            _data.rank = result.data.rank;
            if(result && result.data && !result.data.deepLinkUrl) {
              ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: result.id});
            }
            updateMasterItem(ContentItem.item);
          }, errorItem = function () {
            Buildfire.spinner.hide();
            throw console.error('There was a problem fetching your data', err);
          };
          Buildfire.spinner.show();
          DataStore.getById(id, TAG_NAMES.SEMINAR_ITEMS).then(successItem, errorItem);
        };

        /**
         * Add dynamic link
         */

        ContentItem.addLink = function () {
          var options = {showIcons: false};
          var callback = function (error, result) {
            if (error) {
              return console.error('Error:', error);
            }
            if (!ContentItem.item.data.links)
              ContentItem.item.data.links = [];
            if (result.title)
              ContentItem.item.data.links.push(result);
            $scope.$digest();
          };
          Buildfire.actionItems.showDialog(null, options, callback);
        };

        /**
         * Remove dynamic link
         */

        ContentItem.removeLink = function (index) {
          if (ContentItem.item.data && ContentItem.item.data.links) {
            ContentItem.item.data.links.splice(index, 1);
          }
        };

        /**
         * Edit dynamic link
         */

        ContentItem.editLink = function (link, index) {
          Buildfire.actionItems.showDialog(link, linkOptions, function editLinkCallback(error, result) {
            if (error) {
              return console.error('Error:', error);
            }
            if (!ContentItem.item.data.links) {
              ContentItem.item.data.links = [];
            }
            if (result === null) {
              return console.error('Error:Can not save data, Null record found.');
            }
            ContentItem.item.data.links.splice(index, 1, result);
            $scope.$digest();
          });
        };

        ContentItem.goToHome = function () {
            buildfire.messaging.sendMessageToWidget({});
          $location.path('#/');
        };

        var tmrDelayForItem = null;

        var updateItemsWithDelay = function (item) {
          clearTimeout(tmrDelayForItem);
          ContentItem.isUpdating = false;
          ContentItem.unchangedData = angular.equals(_data, ContentItem.item.data);

          ContentItem.isItemValid = ContentItem.isValidItem(ContentItem.item.data);
          if (!ContentItem.isUpdating && !isUnchanged(ContentItem.item) && ContentItem.isItemValid) {
            tmrDelayForItem = setTimeout(function () {
              if (item.id) {
                ContentItem.updateItemData();
              } else if (!ContentItem.isNewItemInserted) {
                ContentItem.addNewItem();
              }
            }, 300);
          }
        };

        $scope.$watch(function () {
          return ContentItem.item;
        }, updateItemsWithDelay, true);

      }]);
})(window.angular, window.buildfire);<|endoftext|>


<commit_before>const express = require('../../../../shared/express');
const url = require('url');
const querystring = require('querystring');
const debug = require('@tryghost/debug')('web:shared:mw:custom-redirects');
const config = require('../../../../shared/config');
const urlUtils = require('../../../../shared/url-utils');
const errors = require('@tryghost/errors');
const i18n = require('../../../../shared/i18n');
const logging = require('@tryghost/logging');
const redirectsService = require('../../../services/redirects');
const labsService = require('../../../../shared/labs');

const _private = {};

let customRedirectsRouter;

_private.registerRoutes = () => {
    debug('redirects loading');

    customRedirectsRouter = express.Router('redirects');

    try {
        const redirects = redirectsService.loadRedirectsFile();

        if (labsService.isSet('offers')) {
            redirects.unshift({
                from: '/zimo50',
                to: '/#/portal/offers/abcdefuckoff'
            });
        }

        redirectsService.validate(redirects);

        redirects.forEach((redirect) => {
            /**
             * Detect case insensitive modifier when regex is enclosed by
             * / ... /i
             */
            let options = '';
            if (redirect.from.match(/^\/.*\/i$/)) {
                redirect.from = redirect.from.slice(1, -2);
                options = 'i';
            }

            /**
             * always delete trailing slashes, doesn't matter if regex or not
             * Example:
             *   - you define /my-blog-post-1/ as from property
             *   - /my-blog-post-1 or /my-blog-post-1/ should work
             */

            if (redirect.from.match(/\/$/)) {
                redirect.from = redirect.from.slice(0, -1);
            }

            if (redirect.from[redirect.from.length - 1] !== '$') {
                redirect.from += '/?$';
            }

            debug('register', redirect.from);
            customRedirectsRouter.get(new RegExp(redirect.from, options), function (req, res) {
                const maxAge = redirect.permanent ? config.get('caching:customRedirects:maxAge') : 0;
                const toURL = url.parse(redirect.to);
                const toURLParams = querystring.parse(toURL.query);
                const currentURL = url.parse(req.url);
                const currentURLParams = querystring.parse(currentURL.query);
                const params = Object.assign({}, currentURLParams, toURLParams);
                const search = querystring.stringify(params);

                toURL.pathname = currentURL.pathname.replace(new RegExp(redirect.from, options), toURL.pathname);
                toURL.search = search !== '' ? `?${search}` : null;

                /**
                 * Only if the URL is internal should we prepend the Ghost subdirectory
                 * @see https://github.com/TryGhost/Ghost/issues/10776
                 */
                if (!toURL.hostname) {
                    toURL.pathname = urlUtils.urlJoin(urlUtils.getSubdir(), toURL.pathname);
                }

                res.set({
                    'Cache-Control': `public, max-age=${maxAge}`
                });

                res.redirect(redirect.permanent ? 301 : 302, url.format(toURL));
            });
        });
    } catch (err) {
        if (errors.utils.isIgnitionError(err)) {
            logging.error(err);
        } else {
            logging.error(new errors.IncorrectUsageError({
                message: i18n.t('errors.middleware.redirects.register'),
                context: err.message,
                help: 'https://ghost.org/docs/themes/routing/#redirects',
                err
            }));
        }
    }

    debug('redirects loaded');
};

/**
 * - you can extend Ghost with a custom redirects file
 * - see https://github.com/TryGhost/Ghost/issues/7707 and https://ghost.org/docs/themes/routing/#redirects
 * - file loads synchronously, because we need to register the routes before anything else
 */
exports.use = function use(siteApp) {
    _private.registerRoutes();

    // Recommended approach by express, see https://github.com/expressjs/express/issues/2596#issuecomment-81353034.
    // As soon as the express router get's re-instantiated, the old router instance is not used anymore.
    siteApp.use(function customRedirect(req, res, next) {
        customRedirectsRouter(req, res, next);
    });
};

exports.reload = function reload() {
    _private.registerRoutes();
};
<commit_msg>Refactored i18n out of custom redirects middleware<commit_after>const express = require('../../../../shared/express');
const url = require('url');
const querystring = require('querystring');
const debug = require('@tryghost/debug')('web:shared:mw:custom-redirects');
const config = require('../../../../shared/config');
const urlUtils = require('../../../../shared/url-utils');
const errors = require('@tryghost/errors');
const logging = require('@tryghost/logging');
const redirectsService = require('../../../services/redirects');
const labsService = require('../../../../shared/labs');

const messages = {
    customRedirectsRegistrationFailure: 'Could not register custom redirects.'
};

const _private = {};

let customRedirectsRouter;

_private.registerRoutes = () => {
    debug('redirects loading');

    customRedirectsRouter = express.Router('redirects');

    try {
        const redirects = redirectsService.loadRedirectsFile();

        if (labsService.isSet('offers')) {
            redirects.unshift({
                from: '/zimo50',
                to: '/#/portal/offers/abcdefuckoff'
            });
        }

        redirectsService.validate(redirects);

        redirects.forEach((redirect) => {
            /**
             * Detect case insensitive modifier when regex is enclosed by
             * / ... /i
             */
            let options = '';
            if (redirect.from.match(/^\/.*\/i$/)) {
                redirect.from = redirect.from.slice(1, -2);
                options = 'i';
            }

            /**
             * always delete trailing slashes, doesn't matter if regex or not
             * Example:
             *   - you define /my-blog-post-1/ as from property
             *   - /my-blog-post-1 or /my-blog-post-1/ should work
             */

            if (redirect.from.match(/\/$/)) {
                redirect.from = redirect.from.slice(0, -1);
            }

            if (redirect.from[redirect.from.length - 1] !== '$') {
                redirect.from += '/?$';
            }

            debug('register', redirect.from);
            customRedirectsRouter.get(new RegExp(redirect.from, options), function (req, res) {
                const maxAge = redirect.permanent ? config.get('caching:customRedirects:maxAge') : 0;
                const toURL = url.parse(redirect.to);
                const toURLParams = querystring.parse(toURL.query);
                const currentURL = url.parse(req.url);
                const currentURLParams = querystring.parse(currentURL.query);
                const params = Object.assign({}, currentURLParams, toURLParams);
                const search = querystring.stringify(params);

                toURL.pathname = currentURL.pathname.replace(new RegExp(redirect.from, options), toURL.pathname);
                toURL.search = search !== '' ? `?${search}` : null;

                /**
                 * Only if the URL is internal should we prepend the Ghost subdirectory
                 * @see https://github.com/TryGhost/Ghost/issues/10776
                 */
                if (!toURL.hostname) {
                    toURL.pathname = urlUtils.urlJoin(urlUtils.getSubdir(), toURL.pathname);
                }

                res.set({
                    'Cache-Control': `public, max-age=${maxAge}`
                });

                res.redirect(redirect.permanent ? 301 : 302, url.format(toURL));
            });
        });
    } catch (err) {
        if (errors.utils.isIgnitionError(err)) {
            logging.error(err);
        } else {
            logging.error(new errors.IncorrectUsageError({
                message: messages.customRedirectsRegistrationFailure,
                context: err.message,
                help: 'https://ghost.org/docs/themes/routing/#redirects',
                err
            }));
        }
    }

    debug('redirects loaded');
};

/**
 * - you can extend Ghost with a custom redirects file
 * - see https://github.com/TryGhost/Ghost/issues/7707 and https://ghost.org/docs/themes/routing/#redirects
 * - file loads synchronously, because we need to register the routes before anything else
 */
exports.use = function use(siteApp) {
    _private.registerRoutes();

    // Recommended approach by express, see https://github.com/expressjs/express/issues/2596#issuecomment-81353034.
    // As soon as the express router get's re-instantiated, the old router instance is not used anymore.
    siteApp.use(function customRedirect(req, res, next) {
        customRedirectsRouter(req, res, next);
    });
};

exports.reload = function reload() {
    _private.registerRoutes();
};
<|endoftext|>