<commit_before>/* globals L */
import Ember from 'ember';

export default Ember.Component.extend({

  setupMap: function () {

    this.mapLayers = this.createMapLayers();

    var mapOptions = {
      layers: [this.mapLayers.baseLayerConf['Topo 2']],
      scrollWheelZoom: false,
      center: this.mapCenter,
      zoom: this.mapZoom
    };

    var view = this.$();
    this.map = L.map(view[0], mapOptions);

    // // Add layer controls for selecting layer to map
    // L.control.layers(this.mapLayers.baseLayerConf, this.mapLayers.overlayConf, {
    //   position: 'topleft'
    // }).addTo(this.map);

  }.on('didInsertElement'),

  createMapLayers: function () {
    var topo, summer, winter, cabin, baseLayerConf, overlayConf;

    topo =  L.tileLayer('http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&zoom={z}&x={x}&y={y}', {
      maxZoom: 16,
      attribution: 'Statens kartverk'
    });

    summer = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_summer/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    winter = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_winter/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    cabin = L.tileLayer('http://mt3.turistforeningen.no/prod/cabin/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    baseLayerConf = {'Topo 2': topo};
    overlayConf = {
      'DNTs merkede stier': summer,
      'DNTs merkede vinterruter': winter,
      'DNTs turisthytter': cabin
    };

    return {
      baseLayerConf: baseLayerConf,
      overlayConf: overlayConf
    };
},
});
<commit_msg>Add properties center & zoom and bind with what's passed to the component<commit_after>/* globals L */
import Ember from 'ember';

export default Ember.Component.extend({

  center: null,
  zoom: 13,

  bindAttributes: ['center', 'zoom'],

  setupMap: function () {

    this.mapLayers = this.createMapLayers();

    var mapOptions = {
      layers: [this.mapLayers.baseLayerConf['Topo 2']],
      scrollWheelZoom: false,
      center: this.mapCenter,
      zoom: this.mapZoom
    };

    var view = this.$();
    this.map = L.map(view[0], mapOptions);

    // // Add layer controls for selecting layer to map
    // L.control.layers(this.mapLayers.baseLayerConf, this.mapLayers.overlayConf, {
    //   position: 'topleft'
    // }).addTo(this.map);

  }.on('didInsertElement'),

  createMapLayers: function () {
    var topo, summer, winter, cabin, baseLayerConf, overlayConf;

    topo =  L.tileLayer('http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&zoom={z}&x={x}&y={y}', {
      maxZoom: 16,
      attribution: 'Statens kartverk'
    });

    summer = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_summer/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    winter = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_winter/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    cabin = L.tileLayer('http://mt3.turistforeningen.no/prod/cabin/{z}/{x}/{y}.png', {
      maxZoom: 16,
      attribution: 'DNT'
    });

    baseLayerConf = {'Topo 2': topo};
    overlayConf = {
      'DNTs merkede stier': summer,
      'DNTs merkede vinterruter': winter,
      'DNTs turisthytter': cabin
    };

    return {
      baseLayerConf: baseLayerConf,
      overlayConf: overlayConf
    };
},
});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Controller.extend({
  modal: {},
  ctf: null,
  user: {},
  sortCategory: ['name:asc'],
  sortChallenges: ['points:asc', 'id'],
  sortedChallengeboard: {},
  categories: {},
  setSolvedChallenges: function(){
    // Add new challenge to solved if it exists
    var chall_id = this.get('modal.solvedChallenge');
    if (chall_id || chall_id === 0){
      this.get('user.team.solved').addObject(chall_id);
      this.set('modal.solvedChallenge', false);
    }

    // Updated isSolved flag for challenges that are solved
    var solved = this.get('user.team.solved');
    var t = this;
    if(solved){
      solved.forEach(function(challenge_id){
        var challenge = t.store.peekRecord('challenge', challenge_id);
        //challenge.then(function(){
          if(!challenge.get('isSolved')){
            challenge.set('isSolved', true);
          }
        //});
      });
    } // TODO: set challenges isSolved back to false on logout
  }.observes('ctf.challengeboard.categories', 'user', 'modal.solvedChallenge'),
  actions: {
    openLoginModal: function() {
      this.set('modal.isLogin', true);
    },
    openChallenge: function(id) {
      this.store.find('challenge', id).then((challenge) => {
        this.set('modal.challenge', challenge);
      });
      this.set('modal.isChallenge', true);
    },
  }
});<commit_msg>Fixed null challenge issue<commit_after>import Ember from 'ember';

export default Ember.Controller.extend({
  modal: {},
  ctf: null,
  user: {},
  sortCategory: ['name:asc'],
  sortChallenges: ['points:asc', 'id'],
  sortedChallengeboard: {},
  categories: {},
  setSolvedChallenges: function(){
    // Add new challenge to solved if it exists
    var chall_id = this.get('modal.solvedChallenge');
    if (chall_id || chall_id === 0){
      this.get('user.team.solved').addObject(chall_id);
      this.set('modal.solvedChallenge', false);
    }

    // Updated isSolved flag for challenges that are solved
    var solved = this.get('user.team.solved');
    var t = this;
    if(solved){
      solved.forEach(function(challenge_id){
        var challenge = t.store.peekRecord('challenge', challenge_id);
        if (challenge){
          if(!challenge.get('isSolved')){
            challenge.set('isSolved', true);
          }
        }
      });
    } // TODO: set challenges isSolved back to false on logout
  }.observes('ctf.challengeboard.categories', 'user', 'modal.solvedChallenge'),
  actions: {
    openLoginModal: function() {
      this.set('modal.isLogin', true);
    },
    openChallenge: function(id) {
      this.store.find('challenge', id).then((challenge) => {
        this.set('modal.challenge', challenge);
      });
      this.set('modal.isChallenge', true);
    },
  }
});<|endoftext|>


<commit_before>import _ from "lodash";
import inatjs from "inaturalistjs";
import Project from "../shared/models/project";
import { setConfirmModalState } from "../../observations/show/ducks/confirm_modal";

const SET_ATTRIBUTES = "projects-form/project/SET_ATTRIBUTES";

export default function reducer( state = { }, action ) {
  switch ( action.type ) {
    case SET_ATTRIBUTES:
      return Object.assign( { }, state, action.attributes );
    default:
  }
  return state;
}

export function setAttributes( attributes ) {
  return {
    type: SET_ATTRIBUTES,
    attributes
  };
}

export function removeProject( ) {
  $( window ).scrollTop( 0 );
  return setAttributes( { project: null } );
}

export function setProject( p ) {
  return setAttributes( { project: new Project( p ) } );
}

export function createNewProject( type ) {
  return ( dispatch, getState ) => {
    const config = getState( ).config;
    dispatch( setProject( {
      project_type: type,
      user_id: config.currentUser.id,
      admins: [{ user: config.currentUser, role: "manager" }]
    } ) );
    $( window ).scrollTop( 0 );
  };
}

export function loggedIn( state ) {
  return ( state && state.config && state.config.currentUser );
}

export function updateProject( attrs ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    return dispatch( setAttributes( {
      project: new Project( Object.assign( { }, state.form.project, attrs ) )
    } ) );
  };
}

export function setProjectError( field, error ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    dispatch( updateProject( { errors:
      Object.assign( { }, project.errors, { [field]: error } )
    } ) );
  };
}

let titleValidationTimestamp = new Date( ).getTime( );
export function validateProjectTitle( ) {
  return ( dispatch, getState ) => {
    titleValidationTimestamp = new Date( ).getTime( );
    const project = getState( ).form.project;
    if ( !project ) { return null; }
    if ( _.isEmpty( project.title ) ) {
      dispatch( setProjectError( "title", "Project name is required" ) );
      return null;
    }
    if ( project.title.length > 100 ) {
      dispatch( setProjectError( "title", "Project name must be less than 100 characters" ) );
      return null;
    }
    const searchParams = { title_exact: project.title, not_id: project.id, per_page: 1 };
    const timecheck = _.clone( titleValidationTimestamp );
    dispatch( setProjectError( "title", null ) );
    return setTimeout( ( ) => {
      if ( timecheck === titleValidationTimestamp ) {
        inatjs.projects.autocomplete( searchParams ).then( response => {
          if ( _.isEmpty( response.results ) ) {
            dispatch( setProjectError( "title", null ) );
          } else {
            dispatch( setProjectError( "title", "Project name already taken" ) );
          }
        } ).catch( e => console.log( e ) );
      }
    }, 250 );
  };
}

export function setTitle( title ) {
  return dispatch => {
    dispatch( updateProject( { title } ) );
    dispatch( validateProjectTitle( ) );
  };
}

export function setDescription( description ) {
  return dispatch => {
    let descriptionError;
    if ( _.isEmpty( description ) ) {
      descriptionError = "Project summary text is required";
    }
    dispatch( updateProject( { description } ) );
    dispatch( setProjectError( "description", descriptionError ) );
  };
}

export function addProjectRule( operator, operandType, operand ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !operand ) { return; }
    const operandID = operandType ? operand.id : operand;

    const newRules = [];
    let ruleExists = false;
    _.each( project.project_observation_rules, rule => {
      const isMatch = (
        operator === rule.operator &&
        operandType === rule.operand_type &&
        operandID === rule.operand_id
      );
      if ( isMatch && rule._destroy ) {
        newRules.push( Object.assign( { }, rule, { _destroy: false } ) );
        ruleExists = true;
      } else {
        ruleExists = ruleExists || isMatch;
        newRules.push( rule );
      }
    } );
    if ( !ruleExists ) {
      const newRule = {
        operator,
        operand_type: operandType,
        operand_id: operandID
      };
      if ( operandType ) {
        const instanceName = operandType.toLowerCase( );
        newRule[instanceName] = operand;
      }
      newRules.push( newRule );
    }
    dispatch( updateProject( { project_observation_rules: newRules } ) );
  };
}

export function removeProjectRule( ruleToRemove ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !ruleToRemove ) { return; }
    const newRules = [];
    _.each( project.project_observation_rules, rule => {
      if ( ( ruleToRemove.id && rule.id && ruleToRemove.id === rule.id ) ||
           ( ruleToRemove.operator === rule.operator &&
             ruleToRemove.operand_type === rule.operand_type &&
             ruleToRemove.operand_id === rule.operand_id ) ) {
        // if the rule already exists in the database, mark it as to be destroyed
        // otherwise, just leave the rule off new rule list
        if ( rule.id ) {
          newRules.push( Object.assign( { }, rule, { _destroy: true } ) );
        }
      } else {
        newRules.push( rule );
      }
    } );
    dispatch( updateProject( { project_observation_rules: newRules } ) );
  };
}

export function addManager( user ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !user ) { return; }
    const newAdmins = [];
    let managerExists = false;
    _.each( project.admins, admin => {
      const isMatch = ( admin.user.id === user.id );
      if ( isMatch && admin._destroy ) {
        newAdmins.push( Object.assign( { }, admin, { _destroy: false } ) );
        managerExists = true;
      } else {
        managerExists = managerExists || isMatch;
        newAdmins.push( admin );
      }
    } );
    if ( !managerExists ) {
      newAdmins.push( { user, role: "manager" } );
    }
    dispatch( updateProject( { admins: newAdmins } ) );
  };
}

export function removeProjectUser( projectUser ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !projectUser ) { return; }
    const newAdmins = [];
    _.each( project.admins, admin => {
      if ( projectUser.id && admin.id && projectUser.id === admin.id ) {
        newAdmins.push( Object.assign( { }, admin, { _destroy: true } ) );
      } else if ( projectUser.user.id !== admin.user.id ) {
        newAdmins.push( admin );
      }
    } );
    dispatch( updateProject( { admins: newAdmins } ) );
  };
}

export function setRulePreference( field, value ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !field ) { return; }
    project.rule_preferences = _.reject( project.rule_preferences, pref => pref.field === field );
    project.rule_preferences.push( { field, value } );
    let dateType = project.date_type;
    if ( field === "observed_on" ) {
      dateType = "exact";
    } else if ( field === "d1" || field === "d2" ) {
      dateType = "range";
    } else if ( field === "month" ) {
      dateType = "months";
    }
    dispatch( updateProject( {
      rule_preferences: project.rule_preferences,
      date_type: dateType
    } ) );
  };
}

export function showError( e ) {
  return dispatch => {
    if ( e.response ) {
      e.response.text( ).then( text => ( text ? JSON.parse( text ) : text ) ).then( json => {
        console.log( json );
        alert( JSON.stringify( json.error.original ) );
      } );
    } else {
      alert( e );
    }
    dispatch( updateProject( { saving: false } ) );
  };
}

export function onFileDrop( droppedFiles, field ) {
  return dispatch => {
    if ( _.isEmpty( droppedFiles ) ) { return; }
    const droppedFile = droppedFiles[0];
    if ( droppedFile.type.match( /^image\// ) ) {
      dispatch( updateProject( {
        [field]: droppedFile
      } ) );
    }
  };
}

export function deleteProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    if ( !loggedIn( state ) || !project ) { return; }
    dispatch( setConfirmModalState( {
      show: true,
      message: "Are you sure you want to delete this project?",
      confirmText: I18n.t( "yes" ),
      onConfirm: ( ) => {
        setTimeout( ( ) => {
          dispatch( setConfirmModalState( {
            show: true,
            message: "Deleting...",
            hideFooter: true
          } ) );
        }, 1 );
        inatjs.projects.delete( { id: project.id } ).then( ( ) => {
          window.location = `/projects/user/${state.config.currentUser.login}`;
        } ).catch( e => {
          dispatch( showError( e ) );
        } );
      }
    } ) );
  };
}

export function submitProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    if ( !loggedIn( state ) || !project ) { return; }
    const viewerIsAdmin = state.config.currentUser.roles &&
      state.config.currentUser.roles.indexOf( "admin" ) >= 0;
    // check title and description which may not have been validated yet
    // if the user didn't enter text in those fields yet
    let errors;
    if ( _.isEmpty( project.title ) ) {
      dispatch( setProjectError( "title", "Project name is required" ) );
      errors = true;
    }
    if ( _.isEmpty( project.description ) ) {
      dispatch( setProjectError( "description", "Project summary text is required" ) );
      errors = true;
    }
    if ( errors ) { return; }
    const payload = { project: {
      project_type: ( project.project_type === "umbrella" ) ? "umbrella" : "collection",
      user_id: project.user_id || state.config.currentUser.id,
      title: project.title,
      description: project.description,
      icon: project.droppedIcon ? project.droppedIcon : null,
      cover: project.droppedBanner ? project.droppedBanner : null,
      preferred_banner_color: project.banner_color,
      prefers_hide_title: project.hide_title,
      prefers_banner_contain: project.header_image_contain,
      prefers_rule_quality_grade: project.rule_quality_grade ?
        _.keys( project.rule_quality_grade ).join( "," ) : "",
      prefers_rule_photos: _.isEmpty( project.rule_photos ) ? "" : project.rule_photos,
      prefers_rule_sounds: _.isEmpty( project.rule_sounds ) ? "" : project.rule_sounds,
      prefers_rule_term_id: _.isEmpty( project.rule_term_id ) ? "" : project.rule_term_id,
      prefers_rule_term_value_id: _.isEmpty( project.rule_term_value_id ) ?
        "" : project.rule_term_value_id,
      prefers_rule_observed_on:
        ( project.date_type !== "exact" || _.isEmpty( project.rule_observed_on ) ) ?
          "" : project.rule_observed_on.trim( ),
      prefers_rule_d1: project.date_type !== "range" || _.isEmpty( project.rule_d1 ) ?
        "" : project.rule_d1.trim( ),
      prefers_rule_d2: project.date_type !== "range" || _.isEmpty( project.rule_d2 ) ?
        "" : project.rule_d2.trim( ),
      prefers_rule_month: project.date_type !== "months" || _.isEmpty( project.rule_month ) ?
        "" : project.rule_month
    } };
    if ( !payload.project.icon && project.iconDeleted ) {
      payload.icon_delete = true;
    }
    if ( !payload.project.cover && project.bannerDeleted ) {
      payload.cover_delete = true;
    }

    // add project_observation_rules
    payload.project.project_observation_rules_attributes =
      payload.project.project_observation_rules_attributes || [];
    _.each( project.project_observation_rules, rule => {
      if ( ( project.project_type === "umbrella" && rule.operand_type === "Project" ) ||
           ( project.project_type !== "umbrella" &&
             ( rule.operand_type === "Taxon" ||
               rule.operand_type === "User" ||
               rule.operand_type === "Place" ) ) ) {
        const rulePayload = {
          operator: rule.operator,
          operand_type: rule.operand_type,
          operand_id: rule.operand_id
        };
        if ( rule.id ) {
          rulePayload.id = rule.id;
          rulePayload._destroy = !!rule._destroy;
        }
        payload.project.project_observation_rules_attributes.push( rulePayload );
      }
    } );

    // add project_users
    payload.project.admin_attributes =
      payload.project.admin_attributes || [];
    _.each( project.admins, admin => {
      const projectUserPayload = {
        user_id: admin.user.id,
        role: admin.role
      };
      if ( admin.id ) {
        projectUserPayload.id = admin.id;
        projectUserPayload._destroy = !!admin._destroy;
      }
      payload.project.admin_attributes.push( projectUserPayload );
    } );

    dispatch( updateProject( { saving: true } ) );
    if ( project.id ) {
      payload.id = project.slug;
      inatjs.projects.update( payload ).then( ( p ) => {
        window.location = `/projects/${p.slug}`;
      } ).catch( e => {
        dispatch( showError( e ) );
      } );
    } else {
      inatjs.projects.create( payload ).then( ( p ) => {
        window.location = `/projects/${p.slug}`;
      } ).catch( e => {
        dispatch( showError( e ) );
      } );
    }
  };
}

export function confirmSubmitProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    let empty = true;
    const dateType = project.date_type;
    if ( !_.isEmpty( project.rule_quality_grade ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_photos ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_sounds ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_term_id ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_term_value_id ) ) { empty = false; }
    if ( dateType === "exact" && !_.isEmpty( project.rule_observed_on ) ) { empty = false; }
    if ( dateType === "range" && !_.isEmpty( project.rule_d1 ) ) { empty = false; }
    if ( dateType === "range" && !_.isEmpty( project.rule_d2 ) ) { empty = false; }
    if ( dateType === "months" && !_.isEmpty( project.rule_month ) ) { empty = false; }
    if ( !_.isEmpty( project.project_observation_rules ) ) { empty = false; }
    if ( !empty ) {
      dispatch( submitProject( ) );
      return;
    }
    dispatch( setConfirmModalState( {
      show: true,
      message: I18n.t( "views.projects.new.you_have_not_defined_any_observation_requirements" ),
      confirmText: I18n.t( "go_back" ),
      cancelText: I18n.t( "continue" ),
      onCancel: ( ) => {
        dispatch( submitProject( ) );
      }
    } ) );
  };
}
<commit_msg>unset collection project term value rule when term rule is removed<commit_after>import _ from "lodash";
import inatjs from "inaturalistjs";
import Project from "../shared/models/project";
import { setConfirmModalState } from "../../observations/show/ducks/confirm_modal";

const SET_ATTRIBUTES = "projects-form/project/SET_ATTRIBUTES";

export default function reducer( state = { }, action ) {
  switch ( action.type ) {
    case SET_ATTRIBUTES:
      return Object.assign( { }, state, action.attributes );
    default:
  }
  return state;
}

export function setAttributes( attributes ) {
  return {
    type: SET_ATTRIBUTES,
    attributes
  };
}

export function removeProject( ) {
  $( window ).scrollTop( 0 );
  return setAttributes( { project: null } );
}

export function setProject( p ) {
  return setAttributes( { project: new Project( p ) } );
}

export function createNewProject( type ) {
  return ( dispatch, getState ) => {
    const config = getState( ).config;
    dispatch( setProject( {
      project_type: type,
      user_id: config.currentUser.id,
      admins: [{ user: config.currentUser, role: "manager" }]
    } ) );
    $( window ).scrollTop( 0 );
  };
}

export function loggedIn( state ) {
  return ( state && state.config && state.config.currentUser );
}

export function updateProject( attrs ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    return dispatch( setAttributes( {
      project: new Project( Object.assign( { }, state.form.project, attrs ) )
    } ) );
  };
}

export function setProjectError( field, error ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    dispatch( updateProject( { errors:
      Object.assign( { }, project.errors, { [field]: error } )
    } ) );
  };
}

let titleValidationTimestamp = new Date( ).getTime( );
export function validateProjectTitle( ) {
  return ( dispatch, getState ) => {
    titleValidationTimestamp = new Date( ).getTime( );
    const project = getState( ).form.project;
    if ( !project ) { return null; }
    if ( _.isEmpty( project.title ) ) {
      dispatch( setProjectError( "title", "Project name is required" ) );
      return null;
    }
    if ( project.title.length > 100 ) {
      dispatch( setProjectError( "title", "Project name must be less than 100 characters" ) );
      return null;
    }
    const searchParams = { title_exact: project.title, not_id: project.id, per_page: 1 };
    const timecheck = _.clone( titleValidationTimestamp );
    dispatch( setProjectError( "title", null ) );
    return setTimeout( ( ) => {
      if ( timecheck === titleValidationTimestamp ) {
        inatjs.projects.autocomplete( searchParams ).then( response => {
          if ( _.isEmpty( response.results ) ) {
            dispatch( setProjectError( "title", null ) );
          } else {
            dispatch( setProjectError( "title", "Project name already taken" ) );
          }
        } ).catch( e => console.log( e ) );
      }
    }, 250 );
  };
}

export function setTitle( title ) {
  return dispatch => {
    dispatch( updateProject( { title } ) );
    dispatch( validateProjectTitle( ) );
  };
}

export function setDescription( description ) {
  return dispatch => {
    let descriptionError;
    if ( _.isEmpty( description ) ) {
      descriptionError = "Project summary text is required";
    }
    dispatch( updateProject( { description } ) );
    dispatch( setProjectError( "description", descriptionError ) );
  };
}

export function addProjectRule( operator, operandType, operand ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !operand ) { return; }
    const operandID = operandType ? operand.id : operand;

    const newRules = [];
    let ruleExists = false;
    _.each( project.project_observation_rules, rule => {
      const isMatch = (
        operator === rule.operator &&
        operandType === rule.operand_type &&
        operandID === rule.operand_id
      );
      if ( isMatch && rule._destroy ) {
        newRules.push( Object.assign( { }, rule, { _destroy: false } ) );
        ruleExists = true;
      } else {
        ruleExists = ruleExists || isMatch;
        newRules.push( rule );
      }
    } );
    if ( !ruleExists ) {
      const newRule = {
        operator,
        operand_type: operandType,
        operand_id: operandID
      };
      if ( operandType ) {
        const instanceName = operandType.toLowerCase( );
        newRule[instanceName] = operand;
      }
      newRules.push( newRule );
    }
    dispatch( updateProject( { project_observation_rules: newRules } ) );
  };
}

export function removeProjectRule( ruleToRemove ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !ruleToRemove ) { return; }
    const newRules = [];
    _.each( project.project_observation_rules, rule => {
      if ( ( ruleToRemove.id && rule.id && ruleToRemove.id === rule.id ) ||
           ( ruleToRemove.operator === rule.operator &&
             ruleToRemove.operand_type === rule.operand_type &&
             ruleToRemove.operand_id === rule.operand_id ) ) {
        // if the rule already exists in the database, mark it as to be destroyed
        // otherwise, just leave the rule off new rule list
        if ( rule.id ) {
          newRules.push( Object.assign( { }, rule, { _destroy: true } ) );
        }
      } else {
        newRules.push( rule );
      }
    } );
    dispatch( updateProject( { project_observation_rules: newRules } ) );
  };
}

export function addManager( user ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !user ) { return; }
    const newAdmins = [];
    let managerExists = false;
    _.each( project.admins, admin => {
      const isMatch = ( admin.user.id === user.id );
      if ( isMatch && admin._destroy ) {
        newAdmins.push( Object.assign( { }, admin, { _destroy: false } ) );
        managerExists = true;
      } else {
        managerExists = managerExists || isMatch;
        newAdmins.push( admin );
      }
    } );
    if ( !managerExists ) {
      newAdmins.push( { user, role: "manager" } );
    }
    dispatch( updateProject( { admins: newAdmins } ) );
  };
}

export function removeProjectUser( projectUser ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !projectUser ) { return; }
    const newAdmins = [];
    _.each( project.admins, admin => {
      if ( projectUser.id && admin.id && projectUser.id === admin.id ) {
        newAdmins.push( Object.assign( { }, admin, { _destroy: true } ) );
      } else if ( projectUser.user.id !== admin.user.id ) {
        newAdmins.push( admin );
      }
    } );
    dispatch( updateProject( { admins: newAdmins } ) );
  };
}

export function setRulePreference( field, value ) {
  return ( dispatch, getState ) => {
    const project = getState( ).form.project;
    if ( !project || !field ) { return; }
    project.rule_preferences = _.reject( project.rule_preferences, pref => pref.field === field );
    project.rule_preferences.push( { field, value } );
    let dateType = project.date_type;
    if ( field === "observed_on" ) {
      dateType = "exact";
    } else if ( field === "d1" || field === "d2" ) {
      dateType = "range";
    } else if ( field === "month" ) {
      dateType = "months";
    }
    dispatch( updateProject( {
      rule_preferences: project.rule_preferences,
      date_type: dateType
    } ) );
  };
}

export function showError( e ) {
  return dispatch => {
    if ( e.response ) {
      e.response.text( ).then( text => ( text ? JSON.parse( text ) : text ) ).then( json => {
        console.log( json );
        alert( JSON.stringify( json.error.original ) );
      } );
    } else {
      alert( e );
    }
    dispatch( updateProject( { saving: false } ) );
  };
}

export function onFileDrop( droppedFiles, field ) {
  return dispatch => {
    if ( _.isEmpty( droppedFiles ) ) { return; }
    const droppedFile = droppedFiles[0];
    if ( droppedFile.type.match( /^image\// ) ) {
      dispatch( updateProject( {
        [field]: droppedFile
      } ) );
    }
  };
}

export function deleteProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    if ( !loggedIn( state ) || !project ) { return; }
    dispatch( setConfirmModalState( {
      show: true,
      message: "Are you sure you want to delete this project?",
      confirmText: I18n.t( "yes" ),
      onConfirm: ( ) => {
        setTimeout( ( ) => {
          dispatch( setConfirmModalState( {
            show: true,
            message: "Deleting...",
            hideFooter: true
          } ) );
        }, 1 );
        inatjs.projects.delete( { id: project.id } ).then( ( ) => {
          window.location = `/projects/user/${state.config.currentUser.login}`;
        } ).catch( e => {
          dispatch( showError( e ) );
        } );
      }
    } ) );
  };
}

export function submitProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    if ( !loggedIn( state ) || !project ) { return; }
    const viewerIsAdmin = state.config.currentUser.roles &&
      state.config.currentUser.roles.indexOf( "admin" ) >= 0;
    // check title and description which may not have been validated yet
    // if the user didn't enter text in those fields yet
    let errors;
    if ( _.isEmpty( project.title ) ) {
      dispatch( setProjectError( "title", "Project name is required" ) );
      errors = true;
    }
    if ( _.isEmpty( project.description ) ) {
      dispatch( setProjectError( "description", "Project summary text is required" ) );
      errors = true;
    }
    if ( errors ) { return; }
    const payload = { project: {
      project_type: ( project.project_type === "umbrella" ) ? "umbrella" : "collection",
      user_id: project.user_id || state.config.currentUser.id,
      title: project.title,
      description: project.description,
      icon: project.droppedIcon ? project.droppedIcon : null,
      cover: project.droppedBanner ? project.droppedBanner : null,
      preferred_banner_color: project.banner_color,
      prefers_hide_title: project.hide_title,
      prefers_banner_contain: project.header_image_contain,
      prefers_rule_quality_grade: project.rule_quality_grade
        ? _.keys( project.rule_quality_grade ).join( "," ) : "",
      prefers_rule_photos: _.isEmpty( project.rule_photos ) ? "" : project.rule_photos,
      prefers_rule_sounds: _.isEmpty( project.rule_sounds ) ? "" : project.rule_sounds,
      prefers_rule_term_id: _.isEmpty( project.rule_term_id ) ? "" : project.rule_term_id,
      prefers_rule_term_value_id:
        ( _.isEmpty( project.rule_term_value_id ) || _.isEmpty( project.rule_term_id ) )
          ? "" : project.rule_term_value_id,
      prefers_rule_observed_on:
        ( project.date_type !== "exact" || _.isEmpty( project.rule_observed_on ) )
          ? "" : project.rule_observed_on.trim( ),
      prefers_rule_d1: project.date_type !== "range" || _.isEmpty( project.rule_d1 )
        ? "" : project.rule_d1.trim( ),
      prefers_rule_d2: project.date_type !== "range" || _.isEmpty( project.rule_d2 )
        ? "" : project.rule_d2.trim( ),
      prefers_rule_month: project.date_type !== "months" || _.isEmpty( project.rule_month )
        ? "" : project.rule_month
    } };
    if ( !payload.project.icon && project.iconDeleted ) {
      payload.icon_delete = true;
    }
    if ( !payload.project.cover && project.bannerDeleted ) {
      payload.cover_delete = true;
    }

    // add project_observation_rules
    payload.project.project_observation_rules_attributes =
      payload.project.project_observation_rules_attributes || [];
    _.each( project.project_observation_rules, rule => {
      if ( ( project.project_type === "umbrella" && rule.operand_type === "Project" ) ||
           ( project.project_type !== "umbrella" &&
             ( rule.operand_type === "Taxon" ||
               rule.operand_type === "User" ||
               rule.operand_type === "Place" ) ) ) {
        const rulePayload = {
          operator: rule.operator,
          operand_type: rule.operand_type,
          operand_id: rule.operand_id
        };
        if ( rule.id ) {
          rulePayload.id = rule.id;
          rulePayload._destroy = !!rule._destroy;
        }
        payload.project.project_observation_rules_attributes.push( rulePayload );
      }
    } );

    // add project_users
    payload.project.admin_attributes =
      payload.project.admin_attributes || [];
    _.each( project.admins, admin => {
      const projectUserPayload = {
        user_id: admin.user.id,
        role: admin.role
      };
      if ( admin.id ) {
        projectUserPayload.id = admin.id;
        projectUserPayload._destroy = !!admin._destroy;
      }
      payload.project.admin_attributes.push( projectUserPayload );
    } );

    dispatch( updateProject( { saving: true } ) );
    if ( project.id ) {
      payload.id = project.slug;
      inatjs.projects.update( payload ).then( ( p ) => {
        window.location = `/projects/${p.slug}`;
      } ).catch( e => {
        dispatch( showError( e ) );
      } );
    } else {
      inatjs.projects.create( payload ).then( ( p ) => {
        window.location = `/projects/${p.slug}`;
      } ).catch( e => {
        dispatch( showError( e ) );
      } );
    }
  };
}

export function confirmSubmitProject( ) {
  return ( dispatch, getState ) => {
    const state = getState( );
    const project = state.form.project;
    let empty = true;
    const dateType = project.date_type;
    if ( !_.isEmpty( project.rule_quality_grade ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_photos ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_sounds ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_term_id ) ) { empty = false; }
    if ( !_.isEmpty( project.rule_term_value_id ) ) { empty = false; }
    if ( dateType === "exact" && !_.isEmpty( project.rule_observed_on ) ) { empty = false; }
    if ( dateType === "range" && !_.isEmpty( project.rule_d1 ) ) { empty = false; }
    if ( dateType === "range" && !_.isEmpty( project.rule_d2 ) ) { empty = false; }
    if ( dateType === "months" && !_.isEmpty( project.rule_month ) ) { empty = false; }
    if ( !_.isEmpty( project.project_observation_rules ) ) { empty = false; }
    if ( !empty ) {
      dispatch( submitProject( ) );
      return;
    }
    dispatch( setConfirmModalState( {
      show: true,
      message: I18n.t( "views.projects.new.you_have_not_defined_any_observation_requirements" ),
      confirmText: I18n.t( "go_back" ),
      cancelText: I18n.t( "continue" ),
      onCancel: ( ) => {
        dispatch( submitProject( ) );
      }
    } ) );
  };
}
<|endoftext|>


<commit_before>pref("toolkit.defaultChromeURI", "chrome://desktopuploader/content/main.xul");
pref("toolkit.defaultChromeFeatures", "chrome,resizable=yes,dialog=no,centerscreen=yes");
// suppress external-load warning for standard browser schemes
pref("network.protocol-handler.warn-external.http", false);
pref("network.protocol-handler.warn-external.https", false);

/* debugging prefs */
pref("browser.dom.window.dump.enabled", true);
pref("javascript.options.showInConsole", true);
pref("javascript.options.strict", true);
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);
<commit_msg>Don't warn when viewing mixed http/https content.<commit_after>pref("toolkit.defaultChromeURI", "chrome://desktopuploader/content/main.xul");
pref("toolkit.defaultChromeFeatures", "chrome,resizable=yes,dialog=no,centerscreen=yes");
// suppress external-load warning for standard browser schemes
pref("network.protocol-handler.warn-external.http", false);
pref("network.protocol-handler.warn-external.https", false);

/* debugging prefs */
pref("browser.dom.window.dump.enabled", true);
pref("javascript.options.showInConsole", true);
pref("javascript.options.strict", true);
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);
pref("security.warn_viewing_mixed", false);
<|endoftext|>


<commit_before>import SubPage from './subpage';
import { get_detail_view_html } from '../components/detail_view';
import { get_detail_skeleton_html } from '../components/skeleton_state';
import { get_review_html } from '../components/reviews';

erpnext.hub.Item = class Item extends SubPage {
	refresh() {
		this.show_skeleton();
		this.hub_item_code = frappe.get_route()[2];

		this.own_item = false;

		this.get_item(this.hub_item_code)
			.then(item => {
				this.own_item = item.hub_seller === hub.settings.company_email;
				this.item = item;
				this.render(item);
			});
	}

	show_skeleton() {
		this.$wrapper.html(get_detail_skeleton_html());
	}

	get_item(hub_item_code) {
		return hub.call('get_item_details', {
			hub_item_code
		});
	}

	render(item) {
		const html = get_detail_view_html(item, this.own_item);
		this.$wrapper.html(html);

		this.make_review_area();

		this.get_reviews()
			.then(reviews => {
				this.reviews = reviews;
				this.render_reviews();
			});
	}

	edit_details() {
		if (!this.edit_dialog) {
			this.edit_dialog = new frappe.ui.Dialog({
				title: "Edit Your Product",
				fields: []
			});
		}
		this.edit_dialog.show();
	}

	unpublish_item() {
		if(!this.unpublish_dialog) {
			this.unpublish_dialog = new frappe.ui.Dialog({
				title: "Edit Your Product",
				fields: []
			});
		}

		this.unpublish_dialog.show();
	}

	add_to_favourites(favourite_button) {
		$(favourite_button).addClass('disabled');

		hub.call('add_item_to_seller_favourites', {
			hub_item_code: this.hub_item_code,
			hub_seller: hub.settings.company_email
		})
		.then(() => {
			$(favourite_button).html('Saved');
			frappe.show_alert(__('Saved to Favourites'));
			erpnext.hub.trigger('action:item_favourite');
		})
		.catch(e => {
			console.error(e);
		});
	}

	contact_seller() {
		const d = new frappe.ui.Dialog({
			title: __('Send a message'),
			fields: [
				{
					fieldname: 'to',
					fieldtype: 'Read Only',
					label: __('To'),
					default: this.item.company
				},
				{
					fieldtype: 'Text',
					fieldname: 'message',
					label: __('Message')
				}
			],
			primary_action: ({ message }) => {
				if (!message) return;

				hub.call('send_message', {
                    from_seller: hub.settings.company_email,
					to_seller: this.item.hub_seller,
					hub_item: this.item.hub_item_code,
                    message
				})
				.then(() => {
					d.hide();
					frappe.set_route('marketplace', 'messages');
					erpnext.hub.trigger('action:send_message')
				});
			}
		});

		d.show();
	}

	make_review_area() {
		this.comment_area = new frappe.ui.ReviewArea({
			parent: this.$wrapper.find('.timeline-head').empty(),
			mentions: [],
			on_submit: this.on_submit_review.bind(this)
		});
	}

	on_submit_review(values) {
		values.user = frappe.session.user;
		values.username = frappe.session.user_fullname;

		hub.call('add_item_review', {
			hub_item_code: this.hub_item_code,
			review: JSON.stringify(values)
		})
		.then(this.push_review_in_review_area.bind(this));
	}

	push_review_in_review_area(review) {
		this.reviews = this.reviews || [];
		this.reviews.push(review);
		this.render_reviews();

		this.comment_area.reset();
	}

	get_reviews() {
		return hub.call('get_item_reviews', { hub_item_code: this.hub_item_code }).catch(() => {});
	}

	render_reviews() {
		const $timeline = this.$wrapper.find('.timeline-items');

		$timeline.empty();

		const reviews = this.reviews || [];

		reviews.sort((a, b) => {
			if (a.modified > b.modified) {
				return -1;
			}

			if (a.modified  {
			$(get_review_html(review)).appendTo($timeline);
		});
	}
}
<commit_msg>feat: route to message room page after contact seller dialog<commit_after>import SubPage from './subpage';
import { get_detail_view_html } from '../components/detail_view';
import { get_detail_skeleton_html } from '../components/skeleton_state';
import { get_review_html } from '../components/reviews';

erpnext.hub.Item = class Item extends SubPage {
	refresh() {
		this.show_skeleton();
		this.hub_item_code = frappe.get_route()[2];

		this.own_item = false;

		this.get_item(this.hub_item_code)
			.then(item => {
				this.own_item = item.hub_seller === hub.settings.company_email;
				this.item = item;
				this.render(item);
			});
	}

	show_skeleton() {
		this.$wrapper.html(get_detail_skeleton_html());
	}

	get_item(hub_item_code) {
		return hub.call('get_item_details', {
			hub_item_code
		});
	}

	render(item) {
		const html = get_detail_view_html(item, this.own_item);
		this.$wrapper.html(html);

		this.make_review_area();

		this.get_reviews()
			.then(reviews => {
				this.reviews = reviews;
				this.render_reviews();
			});
	}

	edit_details() {
		if (!this.edit_dialog) {
			this.edit_dialog = new frappe.ui.Dialog({
				title: "Edit Your Product",
				fields: []
			});
		}
		this.edit_dialog.show();
	}

	unpublish_item() {
		if(!this.unpublish_dialog) {
			this.unpublish_dialog = new frappe.ui.Dialog({
				title: "Edit Your Product",
				fields: []
			});
		}

		this.unpublish_dialog.show();
	}

	add_to_favourites(favourite_button) {
		$(favourite_button).addClass('disabled');

		hub.call('add_item_to_seller_favourites', {
			hub_item_code: this.hub_item_code,
			hub_seller: hub.settings.company_email
		})
		.then(() => {
			$(favourite_button).html('Saved');
			frappe.show_alert(__('Saved to Favourites'));
			erpnext.hub.trigger('action:item_favourite');
		})
		.catch(e => {
			console.error(e);
		});
	}

	contact_seller() {
		const d = new frappe.ui.Dialog({
			title: __('Send a message'),
			fields: [
				{
					fieldname: 'to',
					fieldtype: 'Read Only',
					label: __('To'),
					default: this.item.company
				},
				{
					fieldtype: 'Text',
					fieldname: 'message',
					label: __('Message')
				}
			],
			primary_action: ({ message }) => {
				if (!message) return;

				hub.call('send_message', {
                    from_seller: hub.settings.company_email,
					to_seller: this.item.hub_seller,
					hub_item: this.item.hub_item_code,
                    message
				})
				.then(() => {
					d.hide();
					frappe.set_route('marketplace', 'buy', this.item.hub_item_code);
					erpnext.hub.trigger('action:send_message')
				});
			}
		});

		d.show();
	}

	make_review_area() {
		this.comment_area = new frappe.ui.ReviewArea({
			parent: this.$wrapper.find('.timeline-head').empty(),
			mentions: [],
			on_submit: this.on_submit_review.bind(this)
		});
	}

	on_submit_review(values) {
		values.user = frappe.session.user;
		values.username = frappe.session.user_fullname;

		hub.call('add_item_review', {
			hub_item_code: this.hub_item_code,
			review: JSON.stringify(values)
		})
		.then(this.push_review_in_review_area.bind(this));
	}

	push_review_in_review_area(review) {
		this.reviews = this.reviews || [];
		this.reviews.push(review);
		this.render_reviews();

		this.comment_area.reset();
	}

	get_reviews() {
		return hub.call('get_item_reviews', { hub_item_code: this.hub_item_code }).catch(() => {});
	}

	render_reviews() {
		const $timeline = this.$wrapper.find('.timeline-items');

		$timeline.empty();

		const reviews = this.reviews || [];

		reviews.sort((a, b) => {
			if (a.modified > b.modified) {
				return -1;
			}

			if (a.modified  {
			$(get_review_html(review)).appendTo($timeline);
		});
	}
}
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var ad = require('../ad');
var utils = require('../utils.js');
var methods = require('./methods.js');
var tstruct = require('./tensorStruct.js');

// fn returns params and grads
function optimize(fn, options) {
	options = utils.mergeDefaults(options, {
		iterations: 100,
		method: methods.sgd(),
		verbose: false
	});

	var iters = options.iterations;
	var method = options.method;
	var verbose = options.verbose;

	for (var i = 0; i < iters; i++) {
		var rets = fn();
		assert(rets.gradients !== undefined);
		assert(rets.parameters !== undefined);
		// TODO: assert that there exists a parameter for each gradient?
		method(rets.gradients, rets.parameters, i);
		if (verbose) {
			console.log('[optimize] done iteration ' + (i+1) + '/' + iters);
		}
	}
}

// Takes an ad function returning { parameters: , loss: }, where both are ad Nodes
// Returns a function which returns { parameters: , gradients: }, where both
//    are Tensors.
// Return function is suitable as input to 'optimize'
function makeOptimizable(fn) {
	return function() {
		var rets = fn();
		assert(rets.parameters !== undefined);
		assert(rets.loss !== undefined);
		// Clear out any derivatives left around from previous iterations
		tstruct.foreach(rets.parameters, [], function(p) {
			p.zeroDerivatives();
		});
		rets.loss.backprop();
		var newrets = {
			gradients: tstruct.map(rets.parameters, ad.derivative),
			parameters: tstruct.map(rets.parameters, ad.value)
		};
		return newrets;
	};
}

// fn is and ad-lifted function which returns { parameters: , loss: }, both
//    of which are ad Nodes
function adOptimize(fn, options) {
	optimize(makeOptimizable(fn), options);
};

// fn is an ad-lifted function which takes some input and returns
//    {output: , parameters: }, both of which are ad Nodes.
// trainingData is list of {input: , output: } tuples
// lossFn is an ad-lifted loss function taking the output of the fn and the
//    ground truth output value and producing a loss
// Constructs minibatches uniformly at random from trainingData
function adTrain(fn, trainingData, lossFn, options) {
	options = utils.mergeDefaults(options, {
		batchSize: 1
	});

	var batchSize = options.batchSize;

	var idx;
	var singleFn = makeOptimizable(function() {
		var trainingDatum = trainingData[idx];
		var rets = fn(trainingDatum.input);
		var loss = lossFn(rets.output, trainingDatum.output);
		return {
			parameters: rets.parameters,
			loss: loss
		};
	});
	var batchFn = function() {
		var gradients;
		var parameters;
		for (var i = 0; i < batchSize; i++) {
			idx = Math.floor(Math.random() * trainingData.length);
			var rets = singleFn();
			if (gradients === undefined) {
				gradients = rets.gradients;
				parameters = rets.parameters;
			} else {
				tstruct.foreach(
					rets.gradients,
					[
						{ struct: gradients, ifMissing: tstruct.ifMissing.zeros },
						{ struct: rets.parameters, ifMissing: tstruct.ifMissing.impossible },
						{ struct: parameters, ifMissing: tstruct.ifMissing.copyFromCoStruct(1) }
					],
					function(newg, g) {
						g.addeq(newg);
					}
				);
			}
		}
		if (batchSize > 1) {
			tstruct.foreach(gradients, [], function(g) {
				g.diveq(batchSize);
			});
		}
		return {
			parameters: parameters,
			gradients: gradients
		};
	}

	optimize(batchFn, options);
}

// Like adTrain, except we use a neural net instead of a lifted ad function
function nnTrain(nn, trainingData, lossFn, options) {
	var fn = function(input) {
		return {
			output: nn.eval(input),
			parameters: nn.getParameters()
		};
	}

	nn.setTraining(true);
	adTrain(fn, trainingData, lossFn, options);
	nn.setTraining(false);
}

module.exports = {
	optimize: optimize,
	adOptimize: adOptimize,
	adTrain: adTrain,
	nnTrain: nnTrain,
};

<commit_msg>optimize(fn, { shuffle: false }) option<commit_after>'use strict';

var assert = require('assert');
var ad = require('../ad');
var utils = require('../utils.js');
var methods = require('./methods.js');
var tstruct = require('./tensorStruct.js');

// fn returns params and grads
function optimize(fn, options) {
	options = utils.mergeDefaults(options, {
		iterations: 100,
		method: methods.sgd(),
		verbose: false
	});

	var iters = options.iterations;
	var method = options.method;
	var verbose = options.verbose;

	for (var i = 0; i < iters; i++) {
		var rets = fn();
		assert(rets.gradients !== undefined);
		assert(rets.parameters !== undefined);
		// TODO: assert that there exists a parameter for each gradient?
		method(rets.gradients, rets.parameters, i);
		if (verbose) {
			console.log('[optimize] done iteration ' + (i+1) + '/' + iters);
		}
	}
}

// Takes an ad function returning { parameters: , loss: }, where both are ad Nodes
// Returns a function which returns { parameters: , gradients: }, where both
//    are Tensors.
// Return function is suitable as input to 'optimize'
function makeOptimizable(fn) {
	return function() {
		var rets = fn();
		assert(rets.parameters !== undefined);
		assert(rets.loss !== undefined);
		// Clear out any derivatives left around from previous iterations
		tstruct.foreach(rets.parameters, [], function(p) {
			p.zeroDerivatives();
		});
		rets.loss.backprop();
		var newrets = {
			gradients: tstruct.map(rets.parameters, ad.derivative),
			parameters: tstruct.map(rets.parameters, ad.value)
		};
		return newrets;
	};
}

// fn is and ad-lifted function which returns { parameters: , loss: }, both
//    of which are ad Nodes
function adOptimize(fn, options) {
	optimize(makeOptimizable(fn), options);
};

// fn is an ad-lifted function which takes some input and returns
//    {output: , parameters: }, both of which are ad Nodes.
// trainingData is list of {input: , output: } tuples
// lossFn is an ad-lifted loss function taking the output of the fn and the
//    ground truth output value and producing a loss
// Constructs minibatches uniformly at random from trainingData
function adTrain(fn, trainingData, lossFn, options) {
	options = utils.mergeDefaults(options, {
		batchSize: 1
	});

	var batchSize = options.batchSize;
	var shuffle = options.shuffle;

	var idx = -1;
	var singleFn = makeOptimizable(function() {
		var trainingDatum = trainingData[idx];
		var rets = fn(trainingDatum.input);
		var loss = lossFn(rets.output, trainingDatum.output);
		return {
			parameters: rets.parameters,
			loss: loss
		};
	});
	var batchFn = function() {
		var gradients;
		var parameters;
		for (var i = 0; i < batchSize; i++) {
			idx = shuffle === false ?
				(idx + 1) % trainingData.length :
				Math.floor(Math.random() * trainingData.length);
			var rets = singleFn();
			if (gradients === undefined) {
				gradients = rets.gradients;
				parameters = rets.parameters;
			} else {
				tstruct.foreach(
					rets.gradients,
					[
						{ struct: gradients, ifMissing: tstruct.ifMissing.zeros },
						{ struct: rets.parameters, ifMissing: tstruct.ifMissing.impossible },
						{ struct: parameters, ifMissing: tstruct.ifMissing.copyFromCoStruct(1) }
					],
					function(newg, g) {
						g.addeq(newg);
					}
				);
			}
		}
		if (batchSize > 1) {
			tstruct.foreach(gradients, [], function(g) {
				g.diveq(batchSize);
			});
		}
		return {
			parameters: parameters,
			gradients: gradients
		};
	}

	optimize(batchFn, options);
}

// Like adTrain, except we use a neural net instead of a lifted ad function
function nnTrain(nn, trainingData, lossFn, options) {
	var fn = function(input) {
		return {
			output: nn.eval(input),
			parameters: nn.getParameters()
		};
	}

	nn.setTraining(true);
	adTrain(fn, trainingData, lossFn, options);
	nn.setTraining(false);
}

module.exports = {
	optimize: optimize,
	adOptimize: adOptimize,
	adTrain: adTrain,
	nnTrain: nnTrain,
};

<|endoftext|>


<commit_before>/**
 * @author alteredq / http://alteredqualia.com/
 * @authod mrdoob / http://mrdoob.com/
 * @authod arodic / http://aleksandarrodic.com/
 * @authod fonserbc / http://fonserbc.github.io/
 *
 * Off-axis stereoscopic effect based on http://paulbourke.net/stereographics/stereorender/
 */

THREE.StereoEffect = function ( renderer ) {

	// API

	this.eyeSeparation = 3;

	/*
	 * Distance to the non-parallax or projection plane
	 */
	this.focalLength = 15;

	// internals

	var _width, _height;

	var _position = new THREE.Vector3();
	var _quaternion = new THREE.Quaternion();
	var _scale = new THREE.Vector3();

	var _cameraL = new THREE.PerspectiveCamera();
	var _cameraR = new THREE.PerspectiveCamera();

	var _fov;
	var _outer, _inner, _top, _bottom;
	var _ndfl, _halfFocalWidth, _halfFocalHeight;
	var _innerFactor, _outerFactor;

	// initialization

	renderer.autoClear = false;

	this.setSize = function ( width, height ) {

		_width = width / 2;
		_height = height;

		renderer.setSize( width, height );

	};

	this.render = function ( scene, camera ) {

		scene.updateMatrixWorld();

		if ( camera.parent === undefined ) camera.updateMatrixWorld();

		camera.matrixWorld.decompose( _position, _quaternion, _scale );

		// Stereo frustum calculation

		// Effective fov of the camera
		_fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( camera.fov ) * 0.5 ) / camera.zoom ) );

		_ndfl = camera.near / this.focalLength;
		_halfFocalHeight = Math.tan( THREE.Math.degToRad( _fov ) * 0.5 ) * this.focalLength;
		_halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;

		_top = _halfFocalHeight * _ndfl;
		_bottom = -_top;
		_innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
		_outerFactor = 1.0 - _innerFactor;

		_outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
		_inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;

		// left

		_cameraL.projectionMatrix.makeFrustum(
			-_outer,
			_inner,
			_bottom,
			_top,
			camera.near,
			camera.far
		);

		_cameraL.position.copy( _position );
		_cameraL.quaternion.copy( _quaternion );
		_cameraL.translateX( - this.eyeSeparation / 2.0 );

		// right

		_cameraR.projectionMatrix.makeFrustum(
			-_inner,
			_outer,
			_bottom,
			_top,
			camera.near,
			camera.far
		);

		_cameraR.position.copy( _position );
		_cameraR.quaternion.copy( _quaternion );
		_cameraR.translateX( this.eyeSeparation / 2.0 );

		//

		renderer.setViewport( 0, 0, _width * 2, _height );
		renderer.clear();

		renderer.setViewport( 0, 0, _width, _height );
		renderer.render( scene, _cameraL );

		renderer.setViewport( _width, 0, _width, _height );
		renderer.render( scene, _cameraR );

	};

};
<commit_msg>StereoEffect: Backwards compatibility.<commit_after>/**
 * @author alteredq / http://alteredqualia.com/
 * @authod mrdoob / http://mrdoob.com/
 * @authod arodic / http://aleksandarrodic.com/
 * @authod fonserbc / http://fonserbc.github.io/
 *
 * Off-axis stereoscopic effect based on http://paulbourke.net/stereographics/stereorender/
 */

THREE.StereoEffect = function ( renderer ) {

	// API

	var scope = this;

	this.eyeSeparation = 3;
	this.focalLength = 15; 	// Distance to the non-parallax or projection plane

	Object.defineProperties( this, {
		separation: {
			get: function () {
				return scope.eyeSeparation;
			},
			set: function ( value ) {
				console.warn( 'THREE.StereoEffect: .separation is now .eyeSeparation.' );
				scope.eyeSeparation = value;
			}
		},
		targetDistance: {
			get: function () {
				return scope.focalLength;
			},
			set: function ( value ) {
				console.warn( 'THREE.StereoEffect: .targetDistance is now .focalLength.' );
				scope.focalLength = value;
			}
		}
	} );

	// internals

	var _width, _height;

	var _position = new THREE.Vector3();
	var _quaternion = new THREE.Quaternion();
	var _scale = new THREE.Vector3();

	var _cameraL = new THREE.PerspectiveCamera();
	var _cameraR = new THREE.PerspectiveCamera();

	var _fov;
	var _outer, _inner, _top, _bottom;
	var _ndfl, _halfFocalWidth, _halfFocalHeight;
	var _innerFactor, _outerFactor;

	// initialization

	renderer.autoClear = false;

	this.setSize = function ( width, height ) {

		_width = width / 2;
		_height = height;

		renderer.setSize( width, height );

	};

	this.render = function ( scene, camera ) {

		scene.updateMatrixWorld();

		if ( camera.parent === undefined ) camera.updateMatrixWorld();

		camera.matrixWorld.decompose( _position, _quaternion, _scale );

		// Effective fov of the camera

		_fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( camera.fov ) * 0.5 ) / camera.zoom ) );

		_ndfl = camera.near / this.focalLength;
		_halfFocalHeight = Math.tan( THREE.Math.degToRad( _fov ) * 0.5 ) * this.focalLength;
		_halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;

		_top = _halfFocalHeight * _ndfl;
		_bottom = -_top;
		_innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
		_outerFactor = 1.0 - _innerFactor;

		_outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
		_inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;

		// left

		_cameraL.projectionMatrix.makeFrustum(
			-_outer,
			_inner,
			_bottom,
			_top,
			camera.near,
			camera.far
		);

		_cameraL.position.copy( _position );
		_cameraL.quaternion.copy( _quaternion );
		_cameraL.translateX( - this.eyeSeparation / 2.0 );

		// right

		_cameraR.projectionMatrix.makeFrustum(
			-_inner,
			_outer,
			_bottom,
			_top,
			camera.near,
			camera.far
		);

		_cameraR.position.copy( _position );
		_cameraR.quaternion.copy( _quaternion );
		_cameraR.translateX( this.eyeSeparation / 2.0 );

		//

		renderer.setViewport( 0, 0, _width * 2, _height );
		renderer.clear();

		renderer.setViewport( 0, 0, _width, _height );
		renderer.render( scene, _cameraL );

		renderer.setViewport( _width, 0, _width, _height );
		renderer.render( scene, _cameraR );

	};

};
<|endoftext|>


<commit_before>'use strict';

var hsl_path = '../../';

var gitsha = $.ajax({
    type: "GET",
    url: hsl_path + 'gitsha.js?t=' + Date.now(),
    async: false
}).responseText;

require.config({
    urlArgs: 'bust=' + gitsha,
    paths: {
        toolbar: hsl_path + 'components/toolbar/toolbar',
        layermanager: hsl_path + 'components/layermanager/layermanager',
        ows: hsl_path + 'components/ows/ows',
        'ows.wms': hsl_path + 'components/ows/ows_wms',
        'ows.wfs': hsl_path + 'components/ows/ows_wfs',
        'ows.nonwms': hsl_path + 'components/ows/ows_nonwms',
        'ows.wmsprioritized': hsl_path + 'components/ows/ows_wmsprioritized',
        query: hsl_path + 'components/query/query',
        search: hsl_path + 'components/search/search',
        print: hsl_path + 'components/print/print',
        permalink: hsl_path + 'components/permalink/permalink',
        geolocation: hsl_path + 'components/geolocation/geolocation',
        measure: hsl_path + 'components/measure/measure',
        legend: hsl_path + 'components/legend/legend',
        app: 'app',
        core: hsl_path + 'components/core/core',
        api: hsl_path + 'components/api/api',
        translations: hsl_path + 'components/translations/js/translations',
        pilsentraffic: hsl_path + 'examples/pilsen_traffic/pilsentraffic',
        ol: hsl_path + 'node_modules/openlayers/dist/ol-debug',
        calendar: hsl_path + 'examples/pilsen_traffic/calendar',
        moment: hsl_path + 'node_modules/moment/min/moment.min',
        ngtimeline: hsl_path + 'bower_components/angular-timelinejs3/dist/js/ng-timeline',
        timeline: hsl_path + 'bower_components/TimelineJS3/compiled/js/timeline'
    },
    shim: {
        d3: {
            exports: 'd3'
        },
        dc: {
            deps: ['d3', 'crossfilter']
        },
        s4a: {
            deps: ['ol', 'dc'],
            exports: 's4a'
        },
        ngtimeline: {
            deps: ['timeline']
        }
    }
});

window.name = "NG_DEFER_BOOTSTRAP!";

require(['core'], function(app) {
    require(['app'], function(app) {
        var $html = angular.element(document.getElementsByTagName('html')[0]);
        angular.element().ready(function() {
            angular.resumeBootstrap([app['name']]);
        });
    });
});
<commit_msg>Dont cache content<commit_after>'use strict';

var hsl_path = '../../';

var gitsha = Math.random(); $.ajax({
    type: "GET",
    dataType: 'text',
    url: hsl_path + 'gitsha.js',
    async: false,
    success: function(r){gitsha = r}
});

require.config({
    urlArgs: 'bust=' + gitsha,
    paths: {
        toolbar: hsl_path + 'components/toolbar/toolbar',
        layermanager: hsl_path + 'components/layermanager/layermanager',
        ows: hsl_path + 'components/ows/ows',
        'ows.wms': hsl_path + 'components/ows/ows_wms',
        'ows.wfs': hsl_path + 'components/ows/ows_wfs',
        'ows.nonwms': hsl_path + 'components/ows/ows_nonwms',
        'ows.wmsprioritized': hsl_path + 'components/ows/ows_wmsprioritized',
        query: hsl_path + 'components/query/query',
        search: hsl_path + 'components/search/search',
        print: hsl_path + 'components/print/print',
        permalink: hsl_path + 'components/permalink/permalink',
        geolocation: hsl_path + 'components/geolocation/geolocation',
        measure: hsl_path + 'components/measure/measure',
        legend: hsl_path + 'components/legend/legend',
        app: 'app',
        core: hsl_path + 'components/core/core',
        api: hsl_path + 'components/api/api',
        translations: hsl_path + 'components/translations/js/translations',
        pilsentraffic: hsl_path + 'examples/pilsen_traffic/pilsentraffic',
        ol: hsl_path + 'node_modules/openlayers/dist/ol-debug',
        calendar: hsl_path + 'examples/pilsen_traffic/calendar',
        moment: hsl_path + 'node_modules/moment/min/moment.min',
        ngtimeline: hsl_path + 'bower_components/angular-timelinejs3/dist/js/ng-timeline',
        timeline: hsl_path + 'bower_components/TimelineJS3/compiled/js/timeline'
    },
    shim: {
        d3: {
            exports: 'd3'
        },
        dc: {
            deps: ['d3', 'crossfilter']
        },
        s4a: {
            deps: ['ol', 'dc'],
            exports: 's4a'
        },
        ngtimeline: {
            deps: ['timeline']
        }
    }
});

window.name = "NG_DEFER_BOOTSTRAP!";

require(['core'], function(app) {
    require(['app'], function(app) {
        var $html = angular.element(document.getElementsByTagName('html')[0]);
        angular.element().ready(function() {
            angular.resumeBootstrap([app['name']]);
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Created by Maxim.Kadushkin on 2/5/2021.
 */

define([
    'core'
], function () {
    'use strict';

    Common.UI.Themes = new (function(locale) {
        !locale && (locale = {});
        var themes_map = {
            'theme-light': {
                text: locale.txtThemeLight || 'Light',
                type: 'light'
            },
            'theme-classic-light': {
                text: locale.txtThemeClassicLight || 'Classic Light',
                type: 'light'
            },
            'theme-dark': {
                text: locale.txtThemeDark || 'Dark',
                type: 'dark'
            },
        }
        var id_default_light_theme = 'theme-classic-light',
            id_default_dark_theme = 'theme-dark';

        var name_colors = [
            "background-normal",
            "background-toolbar",
            "background-toolbar-additional",
            "background-primary-dialog-button",
            "background-tab-underline",
            "background-notification-popover",
            "background-notification-badge",
            "background-scrim",
            "background-loader",

            "highlight-button-hover",
            "highlight-button-pressed",
            "highlight-button-pressed-hover",
            "highlight-primary-dialog-button-hover",
            "highlight-header-button-hover",
            "highlight-header-button-pressed",
            "highlight-toolbar-tab-underline",
            "highlight-text-select",

            "border-toolbar",
            "border-divider",
            "border-regular-control",
            "border-toolbar-button-hover",
            "border-preview-hover",
            "border-preview-select",
            "border-control-focus",
            "border-color-shading",
            "border-error",

            "text-normal",
            "text-normal-pressed",
            "text-secondary",
            "text-tertiary",
            "text-link",
            "text-inverse",
            "text-toolbar-header",
            "text-contrast-background",

            "icon-normal",
            "icon-normal-pressed",
            "icon-inverse",
            "icon-toolbar-header",
            "icon-notification-badge",
            "icon-contrast-popover",
            "icon-success",

            "canvas-background",
            "canvas-content-background",
            "canvas-page-border",

            "canvas-ruler-background",
            "canvas-ruler-margins-background",
            "canvas-ruler-mark",
            "canvas-ruler-handle-border",
            "canvas-ruler-handle-border-disabled",

            "canvas-high-contrast",
            "canvas-high-contrast-disabled",

            "canvas-cell-border",
            "canvas-cell-title-border",
            "canvas-cell-title-border-hover",
            "canvas-cell-title-border-selected",
            "canvas-cell-title-hover",
            "canvas-cell-title-selected",

            "canvas-dark-cell-title",
            "canvas-dark-cell-title-hover",
            "canvas-dark-cell-title-selected",
            "canvas-dark-cell-title-border",
            "canvas-dark-cell-title-border-hover",
            "canvas-dark-cell-title-border-selected",

            "canvas-scroll-thumb",
            "canvas-scroll-thumb-hover",
            "canvas-scroll-thumb-pressed",
            "canvas-scroll-thumb-border",
            "canvas-scroll-thumb-border-hover",
            "canvas-scroll-thumb-border-pressed",
            "canvas-scroll-arrow",
            "canvas-scroll-arrow-hover",
            "canvas-scroll-arrow-pressed",
            "canvas-scroll-thumb-target",
            "canvas-scroll-thumb-target-hover",
            "canvas-scroll-thumb-target-pressed"
        ];

        var get_current_theme_colors = function (colors) {
            var out_object = {};
            if ( !(Common.Utils.isIE10 || Common.Utils.isIE11) ) {
                var style = getComputedStyle(document.body);
                colors.forEach(function (item, index) {
                    out_object[item] = style.getPropertyValue('--' + item).trim()
                })
            }

            return out_object;
        }

        var create_colors_css = function (id, colors) {
            if ( !!colors && !!id ) {
                var _css_array = [':root .', id, '{'];
                for (var c in colors) {
                    _css_array.push('--', c, ':', colors[c], ';');
                }

                _css_array.push('}');
                return _css_array.join('');
            }
        }

        var write_theme_css = function (css) {
            if ( !!css ) {
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = css;
                document.getElementsByTagName('head')[0].appendChild(style);
            }
        }

        var parse_themes_object = function (obj) {
            if ( !!obj.themes && obj.themes instanceof Array ) {
                obj.themes.forEach(function (item) {
                    if ( !!item.id ) {
                        themes_map[item.id] = {text: item.name, type: item.type};
                        write_theme_css(create_colors_css(item.id, item.colors));
                    } else
                    if ( typeof item == 'string' ) {
                        get_themes_config(item)
                    }
                });
            } else
            if ( obj.id ) {
                themes_map[obj.id] = {text: obj.name, type: obj.type};
                write_theme_css( create_colors_css(obj.id, obj.colors) );
            }
        }

        var get_themes_config = function (url) {
            fetch(url, {
                method: 'get',
                headers: {
                    'Accept': 'application/json',
                },
            }).then(function(response) {
                if (!response.ok) {
                    throw new Error('server error');
                }
                return response.json();
            }).then(function(response) {
                if ( response.then ) {
                    // return response.json();
                } else {
                    parse_themes_object(response);

                    /* to break promises chain */
                    throw new Error('loaded');
                }
            }).catch(function(e) {
                if ( e.message == 'loaded' ) {
                } else console.log('fetch error: ' + e);
            });
        }

        var on_document_ready = function (el) {
            // get_themes_config('../../common/main/resources/themes/themes.json')
        }

        return {
            init: function (api) {
                var me = this;

                $(window).on('storage', function (e) {
                    if ( e.key == 'ui-theme' ) {
                        me.setTheme(e.originalEvent.newValue);
                    }
                })

                this.api = api;
                var theme_name = Common.localStorage.getItem('ui-theme', id_default_light_theme);

                if ( !$('body').hasClass(theme_name) ) {
                    $('body').addClass(theme_name);
                }

                var obj = get_current_theme_colors(name_colors);
                obj.type = themes_map[theme_name];
                obj.name = theme_name;
                api.asc_setSkin(obj);

                Common.NotificationCenter.on('document:ready', on_document_ready.bind(this));
            },

            available: function () {
                return !Common.Utils.isIE;
            },

            map: function () {
                return themes_map
            },

            get: function (id) {
                return themes_map[id]
            },

            currentThemeId: function () {
                return Common.localStorage.getItem('ui-theme') || id_default_light_theme;
            },

            defaultThemeId: function (type) {
                return type == 'dark' ? id_default_dark_theme : id_default_light_theme;
            },

            defaultTheme: function (type) {
                return themes_map[this.defaultThemeId(type)]
            },

            isDarkTheme: function () {
                return themes_map[this.currentThemeId()].type == 'dark';
            },

            setTheme: function (id) {
                if ( !!themes_map[id] ) {
                    var classname = document.documentElement.className.replace(/theme-\w+\s?/, '');
                    document.body.className = classname;

                    $('body').addClass(id);

                    var obj = get_current_theme_colors(name_colors);
                    obj.type = themes_map[id].type;
                    obj.name = id;

                    this.api.asc_setSkin(obj);

                    Common.localStorage.setItem('ui-theme', id);
                    Common.NotificationCenter.trigger('uitheme:changed', id);
                }
            },

            toggleTheme: function () {
                this.setTheme( this.isDarkTheme() ? id_default_light_theme : id_default_dark_theme );
            }
        }
    })(Common.UI.Themes);
});
<commit_msg>[themes] fix bug 49875<commit_after>/**
 * Created by Maxim.Kadushkin on 2/5/2021.
 */

define([
    'core'
], function () {
    'use strict';

    Common.UI.Themes = new (function(locale) {
        !locale && (locale = {});
        var themes_map = {
            'theme-light': {
                text: locale.txtThemeLight || 'Light',
                type: 'light'
            },
            'theme-classic-light': {
                text: locale.txtThemeClassicLight || 'Classic Light',
                type: 'light'
            },
            'theme-dark': {
                text: locale.txtThemeDark || 'Dark',
                type: 'dark'
            },
        }
        var id_default_light_theme = 'theme-classic-light',
            id_default_dark_theme = 'theme-dark';

        var name_colors = [
            "background-normal",
            "background-toolbar",
            "background-toolbar-additional",
            "background-primary-dialog-button",
            "background-tab-underline",
            "background-notification-popover",
            "background-notification-badge",
            "background-scrim",
            "background-loader",

            "highlight-button-hover",
            "highlight-button-pressed",
            "highlight-button-pressed-hover",
            "highlight-primary-dialog-button-hover",
            "highlight-header-button-hover",
            "highlight-header-button-pressed",
            "highlight-toolbar-tab-underline",
            "highlight-text-select",

            "border-toolbar",
            "border-divider",
            "border-regular-control",
            "border-toolbar-button-hover",
            "border-preview-hover",
            "border-preview-select",
            "border-control-focus",
            "border-color-shading",
            "border-error",

            "text-normal",
            "text-normal-pressed",
            "text-secondary",
            "text-tertiary",
            "text-link",
            "text-inverse",
            "text-toolbar-header",
            "text-contrast-background",

            "icon-normal",
            "icon-normal-pressed",
            "icon-inverse",
            "icon-toolbar-header",
            "icon-notification-badge",
            "icon-contrast-popover",
            "icon-success",

            "canvas-background",
            "canvas-content-background",
            "canvas-page-border",

            "canvas-ruler-background",
            "canvas-ruler-margins-background",
            "canvas-ruler-mark",
            "canvas-ruler-handle-border",
            "canvas-ruler-handle-border-disabled",

            "canvas-high-contrast",
            "canvas-high-contrast-disabled",

            "canvas-cell-border",
            "canvas-cell-title-border",
            "canvas-cell-title-border-hover",
            "canvas-cell-title-border-selected",
            "canvas-cell-title-hover",
            "canvas-cell-title-selected",

            "canvas-dark-cell-title",
            "canvas-dark-cell-title-hover",
            "canvas-dark-cell-title-selected",
            "canvas-dark-cell-title-border",
            "canvas-dark-cell-title-border-hover",
            "canvas-dark-cell-title-border-selected",

            "canvas-scroll-thumb",
            "canvas-scroll-thumb-hover",
            "canvas-scroll-thumb-pressed",
            "canvas-scroll-thumb-border",
            "canvas-scroll-thumb-border-hover",
            "canvas-scroll-thumb-border-pressed",
            "canvas-scroll-arrow",
            "canvas-scroll-arrow-hover",
            "canvas-scroll-arrow-pressed",
            "canvas-scroll-thumb-target",
            "canvas-scroll-thumb-target-hover",
            "canvas-scroll-thumb-target-pressed"
        ];

        var get_current_theme_colors = function (colors) {
            var out_object = {};
            if ( !(Common.Utils.isIE10 || Common.Utils.isIE11) ) {
                var style = getComputedStyle(document.body);
                colors.forEach(function (item, index) {
                    out_object[item] = style.getPropertyValue('--' + item).trim()
                })
            }

            return out_object;
        }

        var create_colors_css = function (id, colors) {
            if ( !!colors && !!id ) {
                var _css_array = [':root .', id, '{'];
                for (var c in colors) {
                    _css_array.push('--', c, ':', colors[c], ';');
                }

                _css_array.push('}');
                return _css_array.join('');
            }
        }

        var write_theme_css = function (css) {
            if ( !!css ) {
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = css;
                document.getElementsByTagName('head')[0].appendChild(style);
            }
        }

        var parse_themes_object = function (obj) {
            if ( !!obj.themes && obj.themes instanceof Array ) {
                obj.themes.forEach(function (item) {
                    if ( !!item.id ) {
                        themes_map[item.id] = {text: item.name, type: item.type};
                        write_theme_css(create_colors_css(item.id, item.colors));
                    } else
                    if ( typeof item == 'string' ) {
                        get_themes_config(item)
                    }
                });
            } else
            if ( obj.id ) {
                themes_map[obj.id] = {text: obj.name, type: obj.type};
                write_theme_css( create_colors_css(obj.id, obj.colors) );
            }
        }

        var get_themes_config = function (url) {
            fetch(url, {
                method: 'get',
                headers: {
                    'Accept': 'application/json',
                },
            }).then(function(response) {
                if (!response.ok) {
                    throw new Error('server error');
                }
                return response.json();
            }).then(function(response) {
                if ( response.then ) {
                    // return response.json();
                } else {
                    parse_themes_object(response);

                    /* to break promises chain */
                    throw new Error('loaded');
                }
            }).catch(function(e) {
                if ( e.message == 'loaded' ) {
                } else console.log('fetch error: ' + e);
            });
        }

        var on_document_ready = function (el) {
            // get_themes_config('../../common/main/resources/themes/themes.json')
        }

        return {
            init: function (api) {
                var me = this;

                $(window).on('storage', function (e) {
                    if ( e.key == 'ui-theme' ) {
                        me.setTheme(e.originalEvent.newValue);
                    }
                })

                this.api = api;
                var theme_name = Common.localStorage.getItem('ui-theme', id_default_light_theme);

                if ( !$('body').hasClass(theme_name) ) {
                    $('body').addClass(theme_name);
                }

                var obj = get_current_theme_colors(name_colors);
                obj.type = themes_map[theme_name];
                obj.name = theme_name;
                api.asc_setSkin(obj);

                Common.NotificationCenter.on('document:ready', on_document_ready.bind(this));
            },

            available: function () {
                return !Common.Utils.isIE;
            },

            map: function () {
                return themes_map
            },

            get: function (id) {
                return themes_map[id]
            },

            currentThemeId: function () {
                return Common.localStorage.getItem('ui-theme') || id_default_light_theme;
            },

            defaultThemeId: function (type) {
                return type == 'dark' ? id_default_dark_theme : id_default_light_theme;
            },

            defaultTheme: function (type) {
                return themes_map[this.defaultThemeId(type)]
            },

            isDarkTheme: function () {
                return themes_map[this.currentThemeId()].type == 'dark';
            },

            setTheme: function (id) {
                if ( !!themes_map[id] ) {
                    var classname = document.body.className.replace(/theme-\w+\s?/, '');
                    document.body.className = classname;

                    $('body').addClass(id);

                    var obj = get_current_theme_colors(name_colors);
                    obj.type = themes_map[id].type;
                    obj.name = id;

                    this.api.asc_setSkin(obj);

                    Common.localStorage.setItem('ui-theme', id);
                    Common.NotificationCenter.trigger('uitheme:changed', id);
                }
            },

            toggleTheme: function () {
                this.setTheme( this.isDarkTheme() ? id_default_light_theme : id_default_dark_theme );
            }
        }
    })(Common.UI.Themes);
});
<|endoftext|>