<commit_before>// Constants
var M_D_BORDER_WIDTH = 2,
    IS_DIAG_PT_KEY = 'is_diag_pt';

var is_dragging = false,
    is_resizing = false;

var anchor_pt = {x:0, y:0},
    opp_ctrl_pt = {},
    grab_point = {x:0, y:0};
    anchor_x_rat = anchor_y_rat = 0;
    resize_diag = false;                // TRUE if is resizing via a diagonal

var autoplace_timeout,
    AUTOPLACE_TIMOUT_MS = 10000; // Used to reset an auto-place timout

function make_movable_drawing(image_src, image_box, $wb_pane){

    var img_aspect_ratio = image_box.width/image_box.height;

    // Initialize movable drawing
    var img = new Image();
    img.src = image_src;
    img.draggable = false;
    var $m_d = $('<div/>', { class: 'movable' });
    $m_d.css({
        left:            image_box.x - M_D_BORDER_WIDTH,
        top:             image_box.y - M_D_BORDER_WIDTH,
        height:          image_box.height,
        width:           image_box.width,
    });

    // initialize image box size
    img.width = image_box.width; img.height = image_box.height;
    $m_d.append(img);

    $m_d.moved = false; // Flag for whether the image has been moved or not

    // Set an initial autoplace timeout for if user forgets to move or resize image
    set_autoplace_timeout($m_d, $wb_pane);

    $.extend($m_d, {

        start_dragging: function(grabX, grabY){
            toggle_iframe_tarps(true);

            grab_point = {x:grabX, y:grabY};

            is_dragging = true;
            is_resizing = false;
        },

        start_resizing: function($ctrl_pt, $counter_pt){
            toggle_iframe_tarps(true);

            opp_ctrl_pt = $counter_pt;
            anchor_pt.x = $counter_pt.offset().left;
            anchor_pt.y = $counter_pt.offset().top;

            anchor_x_rat = (anchor_pt.x - $m_d.offset().left)/$m_d.width(),
            anchor_y_rat = (anchor_pt.y - $m_d.offset().top)/$m_d.height();

            resize_diag = $ctrl_pt.data(IS_DIAG_PT_KEY);

            is_dragging = false;
            is_resizing = true;
        },

        stop: function(){
            if (is_dragging || is_resizing) {
                is_dragging = is_resizing = false;

                set_autoplace_timeout($m_d, $wb_pane);         // Set m_d to place itself after a timeout

            } else {
                $m_d.place();
                toggle_iframe_tarps(false);
                $wb_pane.set_edit_mode('idle');
            }
        },

        drag_to: function(mouseX, mouseY){
            $m_d.moved = true;
            $m_d.offset({
                top:  mouseY - grab_point.y,
                left: mouseX - grab_point.x
            });
        },

        resize_to: function(mouseX, mouseY){

            $m_d.moved = true;

            var w_scale = Math.abs(mouseX-anchor_pt.x)/$m_d.width(),
                h_scale = Math.abs(mouseY-anchor_pt.y)/$m_d.height();

            // Adjust resizing behaviour based on diagonal vs. axis aligned resize
            var scale = resize_diag ? Math.min(w_scale, h_scale) : Math.max(w_scale, h_scale);

            $m_d.width(  Math.round($m_d.width()*scale));
            $m_d.height( Math.round($m_d.width() / img_aspect_ratio));

            // Move m_d's origin to anchor position
            $m_d.offset({
                top:  anchor_pt.y, left: anchor_pt.x });

            // Now offset by anchor / m_d origin vector
            $m_d.offset({
                top:  anchor_pt.y + (anchor_pt.y-opp_ctrl_pt.offset().top),
                left: anchor_pt.x + (anchor_pt.x-opp_ctrl_pt.offset().left)
            });
        },

        place: function() {
            window.clearTimeout(autoplace_timeout); // Cancel any on-going auto-place timeouts!

            place_img_in_svg($m_d, image_src, $wb_pane.get_svg_root());
            if ($m_d.moved) upload_svg($wb_pane.data('u_id'), $wb_pane.get_svg_root());
            remove_movable_handlers($wb_pane);
            $m_d.remove();
        },

        // Delete SVG from kiosk editor AND from the server
        trash: function() {
            upload_svg($wb_pane.data('u_id'), $wb_pane.get_svg_root());
            remove_movable_handlers($wb_pane);
            $m_d.remove();
        },

        center: function() {
            $m_d.css({ top:  ($m_d.parent().height() - $m_d.height()) / 2,
                       left: ($m_d.parent().width()  - $m_d.width()) / 2    });
        }

    });

    add_control_points($m_d);
    init_movable_handlers($m_d, $wb_pane);

    return $m_d;
}

function set_autoplace_timeout($m_d, $wb_pane){
    window.clearTimeout(autoplace_timeout);
    autoplace_timeout = window.setTimeout(
        function(){

            if (!$wb_pane){
                remove(!m_d);
            } else {
                $m_d.place();
                $wb_pane.set_edit_mode('idle');
            }
            toggle_iframe_tarps(false);

        }, AUTOPLACE_TIMOUT_MS);
}

var CURSOR_CSS = [
    ['nw-resize', 'n-resize', 'ne-resize'],
    ['w-resize',  '',         'e-resize' ],
    ['sw-resize', 's-resize', 'se-resize'], ]

// Adds 9 control points around the edges of the image, similar to Adobe Illustrator etc.
function add_control_points($m_d){

    var ctrl_pts = [[],[],[]];

    // Create control point divs
    for(var i=0; i<3; i++){
        for(var j=0; j<3; j++){

            if (i == 1 && j == 1) continue; // No center control point

            var $ctrl_pt = $('<div/>', {class: 'control-point'});
            $ctrl_pt.css({
                top:     i == 0 ? 0 : i == 1 ? '50%' : 'N/A',
                bottom:  i == 2 ? 0 : 'N/A',
                left:    j == 0 ? 0 : j == 1 ? '50%' : 'N/A',
                right:   j == 2 ? 0 : 'N/A',
                cursor:  CURSOR_CSS[i][j]
            });
            $ctrl_pt.data(IS_DIAG_PT_KEY, (i+j) % 2 == 0);
            $m_d.append($ctrl_pt);
            ctrl_pts[i][j] = $ctrl_pt;
        }
    }

    // Link control points to their opposites
    for(var i=0; i<3; i++){
        for(var j=0; j<3; j++){

            if (i == 1 && j == 1) continue; // Do not handle center control point

            var opp_pt = ctrl_pts[i == 1 ? 1 : (i+2)%4][j == 1 ? 1 : (j+2)%4];
            ctrl_pts[i][j][0].counter_pt = opp_pt;
        }
    }
}

//Simplified handlers for kiosk (mouse only)
function init_movable_handlers($m_d, $wb_pane){

    $m_d.on('mousedown', function(e){
        $m_d.start_dragging(e.offsetX, e.offsetY);
    });

    $wb_pane.on('mousedown.movable','.control-point', function(){
        $m_d.start_resizing($(this), $(this)[0].counter_pt);
        return false;
    });

    $wb_pane.on('mousemove.movable', function(e){
        if (is_resizing === true)
            $m_d.resize_to(e.pageX, e.pageY);
        else if (is_dragging === true)
            $m_d.drag_to(e.pageX, e.pageY);
    });

    $(window).on('mouseup.movable', $m_d.stop);

}

// remove namespaced handlers
function remove_movable_handlers($wb_pane){
    $wb_pane.off('.movable');
    $(window).off('.movable');
}<commit_msg>autoplacing cancelled on trashing a m_d too now<commit_after>// Constants
var M_D_BORDER_WIDTH = 2,
    IS_DIAG_PT_KEY = 'is_diag_pt';

var is_dragging = false,
    is_resizing = false;

var anchor_pt = {x:0, y:0},
    opp_ctrl_pt = {},
    grab_point = {x:0, y:0};
    anchor_x_rat = anchor_y_rat = 0;
    resize_diag = false;                // TRUE if is resizing via a diagonal

var autoplace_timeout,
    AUTOPLACE_TIMOUT_MS = 10000; // Used to reset an auto-place timout

function make_movable_drawing(image_src, image_box, $wb_pane){

    var img_aspect_ratio = image_box.width/image_box.height;

    // Initialize movable drawing
    var img = new Image();
    img.src = image_src;
    img.draggable = false;
    var $m_d = $('<div/>', { class: 'movable' });
    $m_d.css({
        left:            image_box.x - M_D_BORDER_WIDTH,
        top:             image_box.y - M_D_BORDER_WIDTH,
        height:          image_box.height,
        width:           image_box.width,
    });

    // initialize image box size
    img.width = image_box.width; img.height = image_box.height;
    $m_d.append(img);

    $m_d.moved = false; // Flag for whether the image has been moved or not

    // Set an initial autoplace timeout for if user forgets to move or resize image
    set_autoplace_timeout($m_d, $wb_pane);

    $.extend($m_d, {

        start_dragging: function(grabX, grabY){
            toggle_iframe_tarps(true);

            grab_point = {x:grabX, y:grabY};

            is_dragging = true;
            is_resizing = false;
        },

        start_resizing: function($ctrl_pt, $counter_pt){
            toggle_iframe_tarps(true);

            opp_ctrl_pt = $counter_pt;
            anchor_pt.x = $counter_pt.offset().left;
            anchor_pt.y = $counter_pt.offset().top;

            anchor_x_rat = (anchor_pt.x - $m_d.offset().left)/$m_d.width(),
            anchor_y_rat = (anchor_pt.y - $m_d.offset().top)/$m_d.height();

            resize_diag = $ctrl_pt.data(IS_DIAG_PT_KEY);

            is_dragging = false;
            is_resizing = true;
        },

        stop: function(){
            if (is_dragging || is_resizing) {
                is_dragging = is_resizing = false;

                set_autoplace_timeout($m_d, $wb_pane);         // Set m_d to place itself after a timeout

            } else {
                $m_d.place();
                toggle_iframe_tarps(false);
                $wb_pane.set_edit_mode('idle');
            }
        },

        drag_to: function(mouseX, mouseY){
            $m_d.moved = true;
            $m_d.offset({
                top:  mouseY - grab_point.y,
                left: mouseX - grab_point.x
            });
        },

        resize_to: function(mouseX, mouseY){

            $m_d.moved = true;

            var w_scale = Math.abs(mouseX-anchor_pt.x)/$m_d.width(),
                h_scale = Math.abs(mouseY-anchor_pt.y)/$m_d.height();

            // Adjust resizing behaviour based on diagonal vs. axis aligned resize
            var scale = resize_diag ? Math.min(w_scale, h_scale) : Math.max(w_scale, h_scale);

            $m_d.width(  Math.round($m_d.width()*scale));
            $m_d.height( Math.round($m_d.width() / img_aspect_ratio));

            // Move m_d's origin to anchor position
            $m_d.offset({
                top:  anchor_pt.y, left: anchor_pt.x });

            // Now offset by anchor / m_d origin vector
            $m_d.offset({
                top:  anchor_pt.y + (anchor_pt.y-opp_ctrl_pt.offset().top),
                left: anchor_pt.x + (anchor_pt.x-opp_ctrl_pt.offset().left)
            });
        },

        place: function() {
            window.clearTimeout(autoplace_timeout); // Cancel any on-going auto-place timeouts!

            place_img_in_svg($m_d, image_src, $wb_pane.get_svg_root());
            if ($m_d.moved) upload_svg($wb_pane.data('u_id'), $wb_pane.get_svg_root());
            remove_movable_handlers($wb_pane);
            $m_d.remove();
        },

        // Delete SVG from kiosk editor AND from the server
        trash: function() {
            window.clearTimeout(autoplace_timeout);

            upload_svg($wb_pane.data('u_id'), $wb_pane.get_svg_root());
            remove_movable_handlers($wb_pane);
            $m_d.remove();
        },

        center: function() {
            $m_d.css({ top:  ($m_d.parent().height() - $m_d.height()) / 2,
                       left: ($m_d.parent().width()  - $m_d.width()) / 2    });
        }

    });

    add_control_points($m_d);
    init_movable_handlers($m_d, $wb_pane);

    return $m_d;
}

function set_autoplace_timeout($m_d, $wb_pane){
    window.clearTimeout(autoplace_timeout);
    autoplace_timeout = window.setTimeout(
        function(){

            if (!$wb_pane){
                remove(!m_d);
            } else {
                $m_d.place();
                $wb_pane.set_edit_mode('idle');
            }
            toggle_iframe_tarps(false);
            console.log("AUTOPLACED");

        }, AUTOPLACE_TIMOUT_MS);
}

var CURSOR_CSS = [
    ['nw-resize', 'n-resize', 'ne-resize'],
    ['w-resize',  '',         'e-resize' ],
    ['sw-resize', 's-resize', 'se-resize'], ]

// Adds 9 control points around the edges of the image, similar to Adobe Illustrator etc.
function add_control_points($m_d){

    var ctrl_pts = [[],[],[]];

    // Create control point divs
    for(var i=0; i<3; i++){
        for(var j=0; j<3; j++){

            if (i == 1 && j == 1) continue; // No center control point

            var $ctrl_pt = $('<div/>', {class: 'control-point'});
            $ctrl_pt.css({
                top:     i == 0 ? 0 : i == 1 ? '50%' : 'N/A',
                bottom:  i == 2 ? 0 : 'N/A',
                left:    j == 0 ? 0 : j == 1 ? '50%' : 'N/A',
                right:   j == 2 ? 0 : 'N/A',
                cursor:  CURSOR_CSS[i][j]
            });
            $ctrl_pt.data(IS_DIAG_PT_KEY, (i+j) % 2 == 0);
            $m_d.append($ctrl_pt);
            ctrl_pts[i][j] = $ctrl_pt;
        }
    }

    // Link control points to their opposites
    for(var i=0; i<3; i++){
        for(var j=0; j<3; j++){

            if (i == 1 && j == 1) continue; // Do not handle center control point

            var opp_pt = ctrl_pts[i == 1 ? 1 : (i+2)%4][j == 1 ? 1 : (j+2)%4];
            ctrl_pts[i][j][0].counter_pt = opp_pt;
        }
    }
}

//Simplified handlers for kiosk (mouse only)
function init_movable_handlers($m_d, $wb_pane){

    $m_d.on('mousedown', function(e){
        $m_d.start_dragging(e.offsetX, e.offsetY);
    });

    $wb_pane.on('mousedown.movable','.control-point', function(){
        $m_d.start_resizing($(this), $(this)[0].counter_pt);
        return false;
    });

    $wb_pane.on('mousemove.movable', function(e){
        if (is_resizing === true)
            $m_d.resize_to(e.pageX, e.pageY);
        else if (is_dragging === true)
            $m_d.drag_to(e.pageX, e.pageY);
    });

    $(window).on('mouseup.movable', $m_d.stop);

}

// remove namespaced handlers
function remove_movable_handlers($wb_pane){
    $wb_pane.off('.movable');
    $(window).off('.movable');
}<|endoftext|>


<commit_before>module.exports = exports = factory;
exports.$implements = 'webServer';
exports.$inject = ['config', 'sensors', 'wsApi'];

function factory (services) {
	var express = require('express');
	var http = require('http');
	var config = services.config;

	console.log(services);

	var app = express();
	app.use(basicAuth());
	app.use('/sensor', services.sensors.app);
	app.get('/', redirectToUi);

	var server = http.createServer(app);
	services.wsApi.init(server);

	server.listen(config.webServerPort);

	return {
		server: server,
		app: app
	};
}

function redirectToUi(req, res) {
	// TODO: add this
	res.send('REDIRECTING...');
}

function basicAuth() {
	return function(req, res, next) {
		// TODO: add this
		next();
	};
}<commit_msg>Redirect to UI<commit_after>module.exports = exports = factory;
exports.$implements = 'webServer';
exports.$inject = ['config', 'sensors', 'wsApi'];

function factory (services) {
	var express = require('express');
	var http = require('http');
	var config = services.config;

	console.log(services);

	var app = express();
	app.use(basicAuth());
	app.use('/sensor', services.sensors.app);
	app.get('/', redirectToUi);

	var server = http.createServer(app);
	services.wsApi.init(server);

	server.listen(config.webServerPort);

	return {
		server: server,
		app: app
	};
}

function redirectToUi(req, res) {
	res.redirect('http://homeconsole.me');
}

function basicAuth() {
	return function(req, res, next) {
		// TODO: add this
		next();
	};
}<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
/* eslint no-undef: 'error' */
/* eslint no-param-reassign: ["error", { "props": false }] */
import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import {
  getExploreUrlAndPayload,
  getAnnotationJsonUrl,
} from '../explore/exploreUtils';
import {
  requiresQuery,
  ANNOTATION_SOURCE_TYPES,
} from '../modules/AnnotationTypes';
import { addDangerToast } from '../messageToasts/actions';
import { logEvent } from '../logger/actions';
import { Logger, LOG_ACTIONS_LOAD_CHART } from '../logger/LogUtils';
import getClientErrorObject from '../utils/getClientErrorObject';
import { allowCrossDomain } from '../utils/hostNamesConfig';

export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED';
export function chartUpdateStarted(queryController, latestQueryFormData, key) {
  return {
    type: CHART_UPDATE_STARTED,
    queryController,
    latestQueryFormData,
    key,
  };
}

export const CHART_UPDATE_SUCCEEDED = 'CHART_UPDATE_SUCCEEDED';
export function chartUpdateSucceeded(queryResponse, key) {
  return { type: CHART_UPDATE_SUCCEEDED, queryResponse, key };
}

export const CHART_UPDATE_STOPPED = 'CHART_UPDATE_STOPPED';
export function chartUpdateStopped(key) {
  return { type: CHART_UPDATE_STOPPED, key };
}

export const CHART_UPDATE_TIMEOUT = 'CHART_UPDATE_TIMEOUT';
export function chartUpdateTimeout(statusText, timeout, key) {
  return { type: CHART_UPDATE_TIMEOUT, statusText, timeout, key };
}

export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED';
export function chartUpdateFailed(queryResponse, key) {
  return { type: CHART_UPDATE_FAILED, queryResponse, key };
}

export const CHART_RENDERING_FAILED = 'CHART_RENDERING_FAILED';
export function chartRenderingFailed(error, key, stackTrace) {
  return { type: CHART_RENDERING_FAILED, error, key, stackTrace };
}

export const CHART_RENDERING_SUCCEEDED = 'CHART_RENDERING_SUCCEEDED';
export function chartRenderingSucceeded(key) {
  return { type: CHART_RENDERING_SUCCEEDED, key };
}

export const REMOVE_CHART = 'REMOVE_CHART';
export function removeChart(key) {
  return { type: REMOVE_CHART, key };
}

export const ANNOTATION_QUERY_SUCCESS = 'ANNOTATION_QUERY_SUCCESS';
export function annotationQuerySuccess(annotation, queryResponse, key) {
  return { type: ANNOTATION_QUERY_SUCCESS, annotation, queryResponse, key };
}

export const ANNOTATION_QUERY_STARTED = 'ANNOTATION_QUERY_STARTED';
export function annotationQueryStarted(annotation, queryController, key) {
  return { type: ANNOTATION_QUERY_STARTED, annotation, queryController, key };
}

export const ANNOTATION_QUERY_FAILED = 'ANNOTATION_QUERY_FAILED';
export function annotationQueryFailed(annotation, queryResponse, key) {
  return { type: ANNOTATION_QUERY_FAILED, annotation, queryResponse, key };
}

export function runAnnotationQuery(
  annotation,
  timeout = 60,
  formData = null,
  key,
) {
  return function(dispatch, getState) {
    const sliceKey = key || Object.keys(getState().charts)[0];
    // make a copy of formData, not modifying original formData
    const fd = {
      ...(formData || getState().charts[sliceKey].latestQueryFormData),
    };

    if (!requiresQuery(annotation.sourceType)) {
      return Promise.resolve();
    }

    const granularity = fd.time_grain_sqla || fd.granularity;
    fd.time_grain_sqla = granularity;
    fd.granularity = granularity;
    const overridesKeys = Object.keys(annotation.overrides);
    if (overridesKeys.includes('since') || overridesKeys.includes('until')) {
      annotation.overrides = {
        ...annotation.overrides,
        time_range: null,
      };
    }
    const sliceFormData = Object.keys(annotation.overrides).reduce(
      (d, k) => ({
        ...d,
        [k]: annotation.overrides[k] || fd[k],
      }),
      {},
    );

    if (fd !== null) {
      const hasExtraFilters = fd.extra_filters && fd.extra_filters.length > 0;
      sliceFormData.extra_filters = hasExtraFilters
        ? fd.extra_filters
        : undefined;
    }

    const isNative = annotation.sourceType === ANNOTATION_SOURCE_TYPES.NATIVE;
    const url = getAnnotationJsonUrl(annotation.value, sliceFormData, isNative);
    const controller = new AbortController();
    const { signal } = controller;

    dispatch(annotationQueryStarted(annotation, controller, sliceKey));

    return SupersetClient.get({
      url,
      signal,
      timeout: timeout * 1000,
    })
      .then(({ json }) =>
        dispatch(annotationQuerySuccess(annotation, json, sliceKey)),
      )
      .catch(response =>
        getClientErrorObject(response).then(err => {
          if (err.statusText === 'timeout') {
            dispatch(
              annotationQueryFailed(
                annotation,
                { error: 'Query Timeout' },
                sliceKey,
              ),
            );
          } else if ((err.error || '').toLowerCase().includes('no data')) {
            dispatch(annotationQuerySuccess(annotation, err, sliceKey));
          } else if (err.statusText !== 'abort') {
            dispatch(annotationQueryFailed(annotation, err, sliceKey));
          }
        }),
      );
  };
}

export const TRIGGER_QUERY = 'TRIGGER_QUERY';
export function triggerQuery(value = true, key) {
  return { type: TRIGGER_QUERY, value, key };
}

// this action is used for forced re-render without fetch data
export const RENDER_TRIGGERED = 'RENDER_TRIGGERED';
export function renderTriggered(value, key) {
  return { type: RENDER_TRIGGERED, value, key };
}

export const UPDATE_QUERY_FORM_DATA = 'UPDATE_QUERY_FORM_DATA';
export function updateQueryFormData(value, key) {
  return { type: UPDATE_QUERY_FORM_DATA, value, key };
}

// in the sql lab -> explore flow, user can inline edit chart title,
// then the chart will be assigned a new slice_id
export const UPDATE_CHART_ID = 'UPDATE_CHART_ID';
export function updateChartId(newId, key = 0) {
  return { type: UPDATE_CHART_ID, newId, key };
}

export const ADD_CHART = 'ADD_CHART';
export function addChart(chart, key) {
  return { type: ADD_CHART, chart, key };
}

export function exploreJSON(
  formData,
  force = false,
  timeout = 60,
  key,
  method,
) {
  return dispatch => {
    const { url, payload } = getExploreUrlAndPayload({
      formData,
      endpointType: 'json',
      force,
      allowDomainSharding: true,
      method,
    });
    const logStart = Logger.getTimestamp();
    const controller = new AbortController();
    const { signal } = controller;

    dispatch(chartUpdateStarted(controller, payload, key));

    let querySettings = {
      url,
      postPayload: { form_data: payload },
      signal,
      timeout: timeout * 1000,
    };
    if (allowCrossDomain) {
      querySettings = {
        ...querySettings,
        mode: 'cors',
        credentials: 'include',
      };
    }

    const clientMethod =
      method === 'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)
        ? SupersetClient.get
        : SupersetClient.post;
    const queryPromise = clientMethod(querySettings)
      .then(({ json }) => {
        dispatch(
          logEvent(LOG_ACTIONS_LOAD_CHART, {
            slice_id: key,
            is_cached: json.is_cached,
            force_refresh: force,
            row_count: json.rowcount,
            datasource: formData.datasource,
            start_offset: logStart,
            ts: new Date().getTime(),
            duration: Logger.getTimestamp() - logStart,
            has_extra_filters:
              formData.extra_filters && formData.extra_filters.length > 0,
            viz_type: formData.viz_type,
          }),
        );
        return dispatch(chartUpdateSucceeded(json, key));
      })
      .catch(response => {
        const appendErrorLog = errorDetails => {
          dispatch(
            logEvent(LOG_ACTIONS_LOAD_CHART, {
              slice_id: key,
              has_err: true,
              error_details: errorDetails,
              datasource: formData.datasource,
              start_offset: logStart,
              ts: new Date().getTime(),
              duration: Logger.getTimestamp() - logStart,
            }),
          );
        };

        if (response.statusText === 'timeout') {
          appendErrorLog('timeout');
          return dispatch(
            chartUpdateTimeout(response.statusText, timeout, key),
          );
        } else if (response.name === 'AbortError') {
          appendErrorLog('abort');
          return dispatch(chartUpdateStopped(key));
        }
        return getClientErrorObject(response).then(parsedResponse => {
          appendErrorLog(parsedResponse.error);
          return dispatch(chartUpdateFailed(parsedResponse, key));
        });
      });

    const annotationLayers = formData.annotation_layers || [];

    return Promise.all([
      queryPromise,
      dispatch(triggerQuery(false, key)),
      dispatch(updateQueryFormData(payload, key)),
      ...annotationLayers.map(x =>
        dispatch(runAnnotationQuery(x, timeout, formData, key)),
      ),
    ]);
  };
}

export const GET_SAVED_CHART = 'GET_SAVED_CHART';
export function getSavedChart(formData, force = false, timeout = 60, key) {
  /*
   * Perform a GET request to `/explore_json`.
   *
   * This will return the payload of a saved chart, optionally filtered by
   * ad-hoc or extra filters from dashboards. Eg:
   *
   *  GET  /explore_json?{"chart_id":1}
   *  GET  /explore_json?{"chart_id":1,"extra_filters":"..."}
   *
   */
  return exploreJSON(formData, force, timeout, key, 'GET');
}

export const POST_CHART_FORM_DATA = 'POST_CHART_FORM_DATA';
export function postChartFormData(formData, force = false, timeout = 60, key) {
  /*
   * Perform a POST request to `/explore_json`.
   *
   * This will post the form data to the endpoint, returning a new chart.
   *
   */
  return exploreJSON(formData, force, timeout, key, 'POST');
}

export function redirectSQLLab(formData) {
  return dispatch => {
    const { url } = getExploreUrlAndPayload({
      formData,
      endpointType: 'query',
    });
    return SupersetClient.post({
      url,
      postPayload: { form_data: formData },
    })
      .then(({ json }) => {
        const redirectUrl = new URL(window.location);
        redirectUrl.pathname = '/superset/sqllab';
        for (const key of redirectUrl.searchParams.keys()) {
          redirectUrl.searchParams.delete(key);
        }
        redirectUrl.searchParams.set('datasourceKey', formData.datasource);
        redirectUrl.searchParams.set('sql', json.query);
        window.open(redirectUrl.href, '_blank');
      })
      .catch(() =>
        dispatch(addDangerToast(t('An error occurred while loading the SQL'))),
      );
  };
}

export function refreshChart(chart, force, timeout) {
  return dispatch => {
    if (
      !chart.latestQueryFormData ||
      Object.keys(chart.latestQueryFormData).length === 0
    ) {
      return;
    }
    dispatch(
      postChartFormData(chart.latestQueryFormData, force, timeout, chart.id),
    );
  };
}
<commit_msg>[perf_logging] Add is_cached status when chart has error (#9009)<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
/* eslint no-undef: 'error' */
/* eslint no-param-reassign: ["error", { "props": false }] */
import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import {
  getExploreUrlAndPayload,
  getAnnotationJsonUrl,
} from '../explore/exploreUtils';
import {
  requiresQuery,
  ANNOTATION_SOURCE_TYPES,
} from '../modules/AnnotationTypes';
import { addDangerToast } from '../messageToasts/actions';
import { logEvent } from '../logger/actions';
import { Logger, LOG_ACTIONS_LOAD_CHART } from '../logger/LogUtils';
import getClientErrorObject from '../utils/getClientErrorObject';
import { allowCrossDomain } from '../utils/hostNamesConfig';

export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED';
export function chartUpdateStarted(queryController, latestQueryFormData, key) {
  return {
    type: CHART_UPDATE_STARTED,
    queryController,
    latestQueryFormData,
    key,
  };
}

export const CHART_UPDATE_SUCCEEDED = 'CHART_UPDATE_SUCCEEDED';
export function chartUpdateSucceeded(queryResponse, key) {
  return { type: CHART_UPDATE_SUCCEEDED, queryResponse, key };
}

export const CHART_UPDATE_STOPPED = 'CHART_UPDATE_STOPPED';
export function chartUpdateStopped(key) {
  return { type: CHART_UPDATE_STOPPED, key };
}

export const CHART_UPDATE_TIMEOUT = 'CHART_UPDATE_TIMEOUT';
export function chartUpdateTimeout(statusText, timeout, key) {
  return { type: CHART_UPDATE_TIMEOUT, statusText, timeout, key };
}

export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED';
export function chartUpdateFailed(queryResponse, key) {
  return { type: CHART_UPDATE_FAILED, queryResponse, key };
}

export const CHART_RENDERING_FAILED = 'CHART_RENDERING_FAILED';
export function chartRenderingFailed(error, key, stackTrace) {
  return { type: CHART_RENDERING_FAILED, error, key, stackTrace };
}

export const CHART_RENDERING_SUCCEEDED = 'CHART_RENDERING_SUCCEEDED';
export function chartRenderingSucceeded(key) {
  return { type: CHART_RENDERING_SUCCEEDED, key };
}

export const REMOVE_CHART = 'REMOVE_CHART';
export function removeChart(key) {
  return { type: REMOVE_CHART, key };
}

export const ANNOTATION_QUERY_SUCCESS = 'ANNOTATION_QUERY_SUCCESS';
export function annotationQuerySuccess(annotation, queryResponse, key) {
  return { type: ANNOTATION_QUERY_SUCCESS, annotation, queryResponse, key };
}

export const ANNOTATION_QUERY_STARTED = 'ANNOTATION_QUERY_STARTED';
export function annotationQueryStarted(annotation, queryController, key) {
  return { type: ANNOTATION_QUERY_STARTED, annotation, queryController, key };
}

export const ANNOTATION_QUERY_FAILED = 'ANNOTATION_QUERY_FAILED';
export function annotationQueryFailed(annotation, queryResponse, key) {
  return { type: ANNOTATION_QUERY_FAILED, annotation, queryResponse, key };
}

export function runAnnotationQuery(
  annotation,
  timeout = 60,
  formData = null,
  key,
) {
  return function(dispatch, getState) {
    const sliceKey = key || Object.keys(getState().charts)[0];
    // make a copy of formData, not modifying original formData
    const fd = {
      ...(formData || getState().charts[sliceKey].latestQueryFormData),
    };

    if (!requiresQuery(annotation.sourceType)) {
      return Promise.resolve();
    }

    const granularity = fd.time_grain_sqla || fd.granularity;
    fd.time_grain_sqla = granularity;
    fd.granularity = granularity;
    const overridesKeys = Object.keys(annotation.overrides);
    if (overridesKeys.includes('since') || overridesKeys.includes('until')) {
      annotation.overrides = {
        ...annotation.overrides,
        time_range: null,
      };
    }
    const sliceFormData = Object.keys(annotation.overrides).reduce(
      (d, k) => ({
        ...d,
        [k]: annotation.overrides[k] || fd[k],
      }),
      {},
    );

    if (fd !== null) {
      const hasExtraFilters = fd.extra_filters && fd.extra_filters.length > 0;
      sliceFormData.extra_filters = hasExtraFilters
        ? fd.extra_filters
        : undefined;
    }

    const isNative = annotation.sourceType === ANNOTATION_SOURCE_TYPES.NATIVE;
    const url = getAnnotationJsonUrl(annotation.value, sliceFormData, isNative);
    const controller = new AbortController();
    const { signal } = controller;

    dispatch(annotationQueryStarted(annotation, controller, sliceKey));

    return SupersetClient.get({
      url,
      signal,
      timeout: timeout * 1000,
    })
      .then(({ json }) =>
        dispatch(annotationQuerySuccess(annotation, json, sliceKey)),
      )
      .catch(response =>
        getClientErrorObject(response).then(err => {
          if (err.statusText === 'timeout') {
            dispatch(
              annotationQueryFailed(
                annotation,
                { error: 'Query Timeout' },
                sliceKey,
              ),
            );
          } else if ((err.error || '').toLowerCase().includes('no data')) {
            dispatch(annotationQuerySuccess(annotation, err, sliceKey));
          } else if (err.statusText !== 'abort') {
            dispatch(annotationQueryFailed(annotation, err, sliceKey));
          }
        }),
      );
  };
}

export const TRIGGER_QUERY = 'TRIGGER_QUERY';
export function triggerQuery(value = true, key) {
  return { type: TRIGGER_QUERY, value, key };
}

// this action is used for forced re-render without fetch data
export const RENDER_TRIGGERED = 'RENDER_TRIGGERED';
export function renderTriggered(value, key) {
  return { type: RENDER_TRIGGERED, value, key };
}

export const UPDATE_QUERY_FORM_DATA = 'UPDATE_QUERY_FORM_DATA';
export function updateQueryFormData(value, key) {
  return { type: UPDATE_QUERY_FORM_DATA, value, key };
}

// in the sql lab -> explore flow, user can inline edit chart title,
// then the chart will be assigned a new slice_id
export const UPDATE_CHART_ID = 'UPDATE_CHART_ID';
export function updateChartId(newId, key = 0) {
  return { type: UPDATE_CHART_ID, newId, key };
}

export const ADD_CHART = 'ADD_CHART';
export function addChart(chart, key) {
  return { type: ADD_CHART, chart, key };
}

export function exploreJSON(
  formData,
  force = false,
  timeout = 60,
  key,
  method,
) {
  return dispatch => {
    const { url, payload } = getExploreUrlAndPayload({
      formData,
      endpointType: 'json',
      force,
      allowDomainSharding: true,
      method,
    });
    const logStart = Logger.getTimestamp();
    const controller = new AbortController();
    const { signal } = controller;

    dispatch(chartUpdateStarted(controller, payload, key));

    let querySettings = {
      url,
      postPayload: { form_data: payload },
      signal,
      timeout: timeout * 1000,
    };
    if (allowCrossDomain) {
      querySettings = {
        ...querySettings,
        mode: 'cors',
        credentials: 'include',
      };
    }

    const clientMethod =
      method === 'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)
        ? SupersetClient.get
        : SupersetClient.post;
    const queryPromise = clientMethod(querySettings)
      .then(({ json }) => {
        dispatch(
          logEvent(LOG_ACTIONS_LOAD_CHART, {
            slice_id: key,
            is_cached: json.is_cached,
            force_refresh: force,
            row_count: json.rowcount,
            datasource: formData.datasource,
            start_offset: logStart,
            ts: new Date().getTime(),
            duration: Logger.getTimestamp() - logStart,
            has_extra_filters:
              formData.extra_filters && formData.extra_filters.length > 0,
            viz_type: formData.viz_type,
          }),
        );
        return dispatch(chartUpdateSucceeded(json, key));
      })
      .catch(response => {
        const appendErrorLog = (errorDetails, isCached) => {
          dispatch(
            logEvent(LOG_ACTIONS_LOAD_CHART, {
              slice_id: key,
              has_err: true,
              is_cached: isCached,
              error_details: errorDetails,
              datasource: formData.datasource,
              start_offset: logStart,
              ts: new Date().getTime(),
              duration: Logger.getTimestamp() - logStart,
            }),
          );
        };

        if (response.statusText === 'timeout') {
          appendErrorLog('timeout');
          return dispatch(
            chartUpdateTimeout(response.statusText, timeout, key),
          );
        } else if (response.name === 'AbortError') {
          appendErrorLog('abort');
          return dispatch(chartUpdateStopped(key));
        }
        return getClientErrorObject(response).then(parsedResponse => {
          // query is processed, but error out.
          appendErrorLog(parsedResponse.error, parsedResponse.is_cached);
          return dispatch(chartUpdateFailed(parsedResponse, key));
        });
      });

    const annotationLayers = formData.annotation_layers || [];

    return Promise.all([
      queryPromise,
      dispatch(triggerQuery(false, key)),
      dispatch(updateQueryFormData(payload, key)),
      ...annotationLayers.map(x =>
        dispatch(runAnnotationQuery(x, timeout, formData, key)),
      ),
    ]);
  };
}

export const GET_SAVED_CHART = 'GET_SAVED_CHART';
export function getSavedChart(formData, force = false, timeout = 60, key) {
  /*
   * Perform a GET request to `/explore_json`.
   *
   * This will return the payload of a saved chart, optionally filtered by
   * ad-hoc or extra filters from dashboards. Eg:
   *
   *  GET  /explore_json?{"chart_id":1}
   *  GET  /explore_json?{"chart_id":1,"extra_filters":"..."}
   *
   */
  return exploreJSON(formData, force, timeout, key, 'GET');
}

export const POST_CHART_FORM_DATA = 'POST_CHART_FORM_DATA';
export function postChartFormData(formData, force = false, timeout = 60, key) {
  /*
   * Perform a POST request to `/explore_json`.
   *
   * This will post the form data to the endpoint, returning a new chart.
   *
   */
  return exploreJSON(formData, force, timeout, key, 'POST');
}

export function redirectSQLLab(formData) {
  return dispatch => {
    const { url } = getExploreUrlAndPayload({
      formData,
      endpointType: 'query',
    });
    return SupersetClient.post({
      url,
      postPayload: { form_data: formData },
    })
      .then(({ json }) => {
        const redirectUrl = new URL(window.location);
        redirectUrl.pathname = '/superset/sqllab';
        for (const key of redirectUrl.searchParams.keys()) {
          redirectUrl.searchParams.delete(key);
        }
        redirectUrl.searchParams.set('datasourceKey', formData.datasource);
        redirectUrl.searchParams.set('sql', json.query);
        window.open(redirectUrl.href, '_blank');
      })
      .catch(() =>
        dispatch(addDangerToast(t('An error occurred while loading the SQL'))),
      );
  };
}

export function refreshChart(chart, force, timeout) {
  return dispatch => {
    if (
      !chart.latestQueryFormData ||
      Object.keys(chart.latestQueryFormData).length === 0
    ) {
      return;
    }
    dispatch(
      postChartFormData(chart.latestQueryFormData, force, timeout, chart.id),
    );
  };
}
<|endoftext|>


<commit_before>//
// Copyright (c) Microsoft and contributors.  All rights reserved.
//
// 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.
//

var fs = require('fs');
if (!fs.existsSync) {
  fs.existsSync = require('path').existsSync;
}

var azure;
if (fs.existsSync('./../../lib/azure.js')) {
  azure = require('./../../lib/azure');
} else {
  azure = require('azure');
}

var util = require('util');

var topic = 'topicsample';
var subscription1 = 'subscription1';
var subscription2 = 'subscription2';

var serviceBusClient = azure.createServiceBusService();

function createTopic() {
  // Step 0: Create topic.
  serviceBusClient.createTopic(topic, function (error) {
    if (error) {
      console.log(error);
    } else {
      console.log('Created the topic ' + topic);
      createSubscriptions();
    }
  });
}

function createSubscriptions() {
  // Step 1: Create subscriptions.
  serviceBusClient.createSubscription(topic, subscription1, function (error1) {
    if (error1) {
      console.log(error1);
    } else {
      serviceBusClient.createSubscription(topic, subscription2, function (error2) {
        if (error2) {
          console.log(error2);
        } else {
          sendMessages();
        }
      });
    }
  });
}

function sendMessages() {
  // Step 2: Send a few messages to later be consumed.
  serviceBusClient.sendTopicMessage(topic, 'Send Message Works', function(error1) {
    if (error1) {
      console.log(error1);
    } else {
      console.log('Sent first Message');
      serviceBusClient.sendTopicMessage(topic, 'Send Message Still Works', function (error2) {
        if (error2) {
          console.log(error2);
        } else {
          console.log('Sent Second Message');
          receiveMessagesSubscription1();
        }
      });
    }
  });
}

function receiveMessagesSubscription1() {
  // Step 3: Receive the messages for subscription 1.
  serviceBusClient.receiveSubscriptionMessage(topic, subscription1, function (error1, message1) {
    if (error1) {
      console.log(error1);
    } else {
      console.log(message1.body);
      serviceBusClient.receiveSubscriptionMessage(topic, subscription1, function (error2, message2) {
        if (error2) {
          console.log(error2);
        } else {
          console.log(message2.body);
          receiveMessagesSubscription2();
        }
      });
    }
  });
}

function receiveMessagesSubscription2() {
  // Step 3: Receive the messages for subscription 2.
  serviceBusClient.receiveSubscriptionMessage(topic, subscription2, function (error1, message1) {
    if (error1) {
      console.log(error1);
    } else {
      console.log(message1.body);
      serviceBusClient.receiveSubscriptionMessage(topic, subscription2, function (error2, message2) {
        if (error2) {
          console.log(error2);
        } else {
          console.log(message2.body);
        }
      });
    }
  });
}

var arguments = process.argv;

if (arguments.length > 3) {
  console.log('Incorrect number of arguments');
}
else if (arguments.length == 3) {
  // Adding a third argument on the command line, whatever it is, will delete the container before running the sample.
  serviceBusClient.deleteTopic(topic, function (error) {
    if (error) {
      console.log(error);
    } else {
      createTopic();
    }
  });
}
else {
  createTopic();
}<commit_msg>Update SB Topic sample<commit_after>//
// Copyright (c) Microsoft and contributors.  All rights reserved.
//
// 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.
//

var fs = require('fs');
var path = require('path');
var azure;
try {
  fs.statSync(path.join(__dirname, './../../lib/azure.js'));
  azure = require('./../../lib/azure');
} catch (error) {
  azure = require('azure');
}

var topic = 'topicsample';
var subscription1 = 'subscription1';
var subscription2 = 'subscription2';

var serviceBusClient = azure.createServiceBusService();

function createTopic() {
  // Step 0: Create topic.
  serviceBusClient.createTopicIfNotExists(topic, function (error, topicCreated, response) {
    if (error) {
      console.log(error);
    } else {
      console.log('Created the topic %s', topic);
      createSubscriptions();
    }
  });
}

function createSubscriptions() {
  // Step 1: Create subscriptions.
  serviceBusClient.createSubscription(topic, subscription1, function (error, result, response) {
    if (error) {
      console.log(error);
    } else {
      serviceBusClient.createSubscription(topic, subscription2, function (error, result, response) {
        if (error) {
          console.log(error);
        } else {
          sendMessages();
        }
      });
    }
  });
}

function sendMessages() {
  // Step 2: Send a few messages to later be consumed.
  serviceBusClient.sendTopicMessage(topic, 'Send Message Works', function (error, response) {
    if (error) {
      console.log(error);
    } else {
      console.log('Sent first Message');
      serviceBusClient.sendTopicMessage(topic, 'Send Message Still Works', function (error, response) {
        if (error) {
          console.log(error);
        } else {
          console.log('Sent Second Message');
          receiveMessagesSubscription1();
        }
      });
    }
  });
}

function receiveMessagesSubscription1() {
  // Step 3: Receive the messages for subscription 1.
  serviceBusClient.receiveSubscriptionMessage(topic, subscription1, function (error, message1, response) {
    if (error) {
      console.log(error);
    } else {
      console.log(message1.body);
      serviceBusClient.receiveSubscriptionMessage(topic, subscription1, function (error, message2, response) {
        if (error) {
          console.log(error);
        } else {
          console.log(message2.body);
          receiveMessagesSubscription2();
        }
      });
    }
  });
}

function receiveMessagesSubscription2() {
  // Step 3: Receive the messages for subscription 2.
  serviceBusClient.receiveSubscriptionMessage(topic, subscription2, function (error, message1, response) {
    if (error) {
      console.log(error);
    } else {
      console.log(message1.body);
      serviceBusClient.receiveSubscriptionMessage(topic, subscription2, function (error, message2, response) {
        if (error) {
          console.log(error);
        } else {
          console.log(message2.body);
        }
      });
    }
  });
}

var args = process.argv;

if (args.length > 3) {
  console.log('Incorrect number of arguments');
} else if (args.length === 3) {
  // Adding a third argument on the command line, whatever it is, will delete the container before running the sample.
  serviceBusClient.deleteTopic(topic, function (error, response) {
    if (error) {
      console.log(error);
    } else {
      createTopic();
    }
  });
} else {
  createTopic();
}
<|endoftext|>


<commit_before>//////////////////////////////
// Walk
//  - A Gulp Plugin
//
// Walks a directory to find all files
//////////////////////////////
'use strict';

//////////////////////////////
// Variables
//////////////////////////////
var through = require('through2'),
    gutil = require('gulp-util'),
    fs = require('fs-extra'),
    path = require('path'),
    fm = require('front-matter'),
    Promise = require('bluebird'),
    PluginError = gutil.PluginError,
    PLUGIN_NAME = 'walk';

var birthTime = function birthTime(a,b) {
  if (a.birthtime < b.birthtime) {
    return -1;
  }
  if (a.birthtime > b.birthtime) {
    return 1;
  }
  return 0;
};

var modTime = function modTime(a,b) {
  if (a.mtime < b.mtime) {
    return -1;
  }
  if (a.mtime > b.mtime) {
    return 1;
  }
  return 0;
}

var pubTime = function modTime(a,b) {
  if (Date.parse(a.meta.published) < Date.parse(b.meta.published)) {
    return -1;
  }
  if (Date.parse(a.meta.published) > Date.parse(b.meta.published)) {
    return 1;
  }
  return 0;
}

var updTime = function modTime(a,b) {
  if (Date.parse(a.meta.updated) < Date.parse(b.updated)) {
    return -1;
  }
  if (Date.parse(a.meta.updated) > Date.parse(b.updated)) {
    return 1;
  }
  return 0;
}

var walker = function (dir, config, cb) {
  var end = [];

  var walk = function(dir, done) {
    var results = [],
        pth,
        pTransform,
        ext,
        content,
        stat;
    fs.readdir(dir, function(err, list) {
      if (err) return done(err);
      var i = 0;
      (function next() {
        var file = list[i++];

        if (!file) return done(null, results);

        file = dir + '/' + file;
        fs.stat(file, function(err, stat) {
          if (stat && stat.isDirectory()) {
            walk(file, function(err, res) {
              results = results.concat(res);
              next();
            });
          } else {
            stat = fs.statSync(file);
            pth = file.split('/');
            pth.shift();
            if (config.settings.transformURL) {
              if (pth[pth.length - 1] !== 'index.html' && pth[pth.length - 1] !== '404.html') {
                pTransform = pth.pop();
                ext = path.extname(file);
                pth.push(pTransform.replace(ext, ''));
                pth.push('index.html');
              }
            }
            else {
              pth[pth.length - 1] = pth[pth.length - 1].replace(ext, '.html');
            }
            pth = pth.join('/');
            stat['path'] = pth;
            stat['file'] = file;
            content = fm(fs.readFileSync(file, 'utf-8'));
            stat['meta'] = content.attributes;

            if (!content.attributes.published) {
              stat.published = stat.birthtime;
            }
            else {
              stat.published = content.attributes.published;
            }

            if (!content.attributes.updated) {
              stat.updated = stat.mtime;
            }
            else {
              stat.updated = content.attributes.updated;
            }

            end.push(stat);
            stat = {};
            results.push(file);
            next();
          }
        });
      })();
    });
  };

  dir = path.join(config.folders.pages, dir);

  return new Promise(function (resolve, reject) {
    walk(dir, function (err, result) {
      if (err) {
        reject(err);
      }
      else {
        resolve(end);
      }
    });
  });
};

//////////////////////////////
// Export
//////////////////////////////
module.exports = function (config) {
  var options = options || {};

  //////////////////////////////
  // Command line arguments for each option
  //////////////////////////////
  process.argv.forEach(function (val, index, array) {
    if (index >= 3) {
      switch (val) {
        case '--fail': options.failOnError = true; break;
      }
    }
  });

  //////////////////////////////
  // Through Object
  //////////////////////////////
  var compile = through.obj(function (file, encoding, cb) {
    var walkAsync,
        _this = this;
    /////////////////////////////
    // Default plugin issues
    //////////////////////////////
    if (file.isNull()) {
      return cb();
    }
    if (file.isStream()) {
      this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
      return cb();
    }

    //////////////////////////////
    // Manipulate Files
    //////////////////////////////

    walkAsync = Promise.promisify(walker);

    if (file.meta.listing) {
      Promise.map(file.meta.listing.folders, function (folder) {
        return walker(folder, config).then(function (results) {
          var base = path.basename(folder);
          var result = {};

          if (file.meta.listing.sort === 'created') {
            results = results.sort(birthTime);
          }
          else if (file.meta.listing.sort === 'modified') {
            results = results.sort(modTime);
          }
          else if (file.meta.listing.sort === 'published') {
            results = results.sort(pubTime);
          }
          else if (file.meta.listing.sort === 'updated') {
            results = results.sort(updTime);
          }

          if (file.meta.listing.reverse) {
            results = results.reverse();
          }

          result[base] = results;

          return result;
        });
      }).then(function (results) {
        var listings = {};

        results.forEach(function (result) {
          var key = Object.keys(result);
          listings[key] = result[key];
        });

        file.meta.listing = listings;

        //////////////////////////////
        // Push the file back to the stream!
        //////////////////////////////
        _this.push(file);

        //////////////////////////////
        // Callback to tell us we're done
        //////////////////////////////
        cb();
      });
    }
    else {
      //////////////////////////////
      // Push the file back to the stream!
      //////////////////////////////
      this.push(file);

      //////////////////////////////
      // Callback to tell us we're done
      //////////////////////////////
      cb();
    }
  })

  return compile;
}
<commit_msg>Add walk ignore<commit_after>//////////////////////////////
// Walk
//  - A Gulp Plugin
//
// Walks a directory to find all files
//////////////////////////////
'use strict';

//////////////////////////////
// Variables
//////////////////////////////
var through = require('through2'),
    gutil = require('gulp-util'),
    fs = require('fs-extra'),
    path = require('path'),
    fm = require('front-matter'),
    Promise = require('bluebird'),
    PluginError = gutil.PluginError,
    PLUGIN_NAME = 'walk';

var birthTime = function birthTime(a,b) {
  if (a.birthtime < b.birthtime) {
    return -1;
  }
  if (a.birthtime > b.birthtime) {
    return 1;
  }
  return 0;
};

var modTime = function modTime(a,b) {
  if (a.mtime < b.mtime) {
    return -1;
  }
  if (a.mtime > b.mtime) {
    return 1;
  }
  return 0;
}

var pubTime = function modTime(a,b) {
  if (Date.parse(a.meta.published) < Date.parse(b.meta.published)) {
    return -1;
  }
  if (Date.parse(a.meta.published) > Date.parse(b.meta.published)) {
    return 1;
  }
  return 0;
}

var updTime = function modTime(a,b) {
  if (Date.parse(a.meta.updated) < Date.parse(b.updated)) {
    return -1;
  }
  if (Date.parse(a.meta.updated) > Date.parse(b.updated)) {
    return 1;
  }
  return 0;
}

var walker = function (dir, config, cb) {
  var end = [];

  var walk = function(dir, done) {
    var results = [],
        pth,
        pTransform,
        ext,
        content,
        stat;
    fs.readdir(dir, function(err, list) {
      if (err) return done(err);
      var i = 0;
      (function next() {
        var file = list[i++];

        if (!file) return done(null, results);

        file = dir + '/' + file;
        fs.stat(file, function(err, stat) {
          var ignore = false;

          if (stat && stat.isDirectory()) {
            walk(file, function(err, res) {
              results = results.concat(res);
              next();
            });
          } else {
            stat = fs.statSync(file);
            pth = file.split('/');
            pth.shift();
            if (config.settings.transformURL) {
              if (pth[pth.length - 1] !== 'index.html' && pth[pth.length - 1] !== '404.html') {
                pTransform = pth.pop();
                ext = path.extname(file);
                pth.push(pTransform.replace(ext, ''));
                pth.push('index.html');
              }
            }
            else {
              pth[pth.length - 1] = pth[pth.length - 1].replace(ext, '.html');
            }
            pth = pth.join('/');
            stat['path'] = pth;
            stat['file'] = file;
            content = fm(fs.readFileSync(file, 'utf-8'));
            stat['meta'] = content.attributes;

            if (!content.attributes.published) {
              stat.published = stat.birthtime;
            }
            else {
              stat.published = content.attributes.published;
            }

            if (!content.attributes.updated) {
              stat.updated = stat.mtime;
            }
            else {
              stat.updated = content.attributes.updated;
            }

            if (config.walker.ignore) {
              config.walker.ignore.forEach(function (ignored) {
                if (stat.meta.hasOwnProperty(ignored.attribute)) {
                  if (ignored.operator === 'is') {
                    ignore = stat.meta[ignored.attribute] === ignored.value;
                  }
                  else if (ignored.operator === 'is not') {
                    ignore = stat.meta[ignored.attribute] !== ignored.value;
                  }
                  else if (ignored.operator === 'gt') {
                    ignore = stat.meta[ignored.attribute] > ignored.value;
                  }
                  else if (ignored.operator === 'lt') {
                    ignore = stat.meta[ignored.attribute] < ignored.value;
                  }
                  else if (ignored.operator === 'gte') {
                    ignore = stat.meta[ignored.attribute] >= ignored.value;
                  }
                  else if (ignored.operator === 'lte') {
                    ignore = stat.meta[ignored.attribute] <= ignored.value;
                  }
                }
              });
            }

            if (!ignore) {
              end.push(stat);
              results.push(file);
            }

            stat = {};
            next();
          }
        });
      })();
    });
  };

  dir = path.join(config.folders.pages, dir);

  return new Promise(function (resolve, reject) {
    walk(dir, function (err, result) {
      if (err) {
        reject(err);
      }
      else {
        resolve(end);
      }
    });
  });
};

//////////////////////////////
// Export
//////////////////////////////
module.exports = function (config) {
  var options = options || {};

  //////////////////////////////
  // Command line arguments for each option
  //////////////////////////////
  process.argv.forEach(function (val, index, array) {
    if (index >= 3) {
      switch (val) {
        case '--fail': options.failOnError = true; break;
      }
    }
  });

  //////////////////////////////
  // Through Object
  //////////////////////////////
  var compile = through.obj(function (file, encoding, cb) {
    var walkAsync,
        _this = this;
    /////////////////////////////
    // Default plugin issues
    //////////////////////////////
    if (file.isNull()) {
      return cb();
    }
    if (file.isStream()) {
      this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
      return cb();
    }

    //////////////////////////////
    // Manipulate Files
    //////////////////////////////

    walkAsync = Promise.promisify(walker);

    if (file.meta.listing) {
      config.walker = file.meta.listing;

      Promise.map(file.meta.listing.folders, function (folder) {
        return walker(folder, config).then(function (results) {
          var base = path.basename(folder);
          var result = {};

          if (file.meta.listing.sort === 'created') {
            results = results.sort(birthTime);
          }
          else if (file.meta.listing.sort === 'modified') {
            results = results.sort(modTime);
          }
          else if (file.meta.listing.sort === 'published') {
            results = results.sort(pubTime);
          }
          else if (file.meta.listing.sort === 'updated') {
            results = results.sort(updTime);
          }

          if (file.meta.listing.reverse) {
            results = results.reverse();
          }

          result[base] = results;

          return result;
        });
      }).then(function (results) {
        var listings = {};

        results.forEach(function (result) {
          var key = Object.keys(result);
          listings[key] = result[key];
        });

        file.meta.listing = listings;

        //////////////////////////////
        // Push the file back to the stream!
        //////////////////////////////
        _this.push(file);

        //////////////////////////////
        // Callback to tell us we're done
        //////////////////////////////
        cb();
      });
    }
    else {
      //////////////////////////////
      // Push the file back to the stream!
      //////////////////////////////
      this.push(file);

      //////////////////////////////
      // Callback to tell us we're done
      //////////////////////////////
      cb();
    }
  })

  return compile;
}
<|endoftext|>


<commit_before>'use strict';

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

var parse = require('../../lib/url_parser');
var expect = require('chai').expect;

// ./node_modules/.bin/mongodb-test-runner -l test/functional/dns_txt_records_tests.js

function getTests() {
  return fs
    .readdirSync(path.join(__dirname, 'specs/dns-txt-records'))
    .filter(x => x.indexOf('json') !== -1)
    .map(x => [x, fs.readFileSync(path.join(__dirname, 'specs/dns-txt-records', x), 'utf8')])
    .map(x => [path.basename(x[0], '.json'), JSON.parse(x[1])]);
}

describe('DNS and TXT record tests', function() {
  getTests().forEach(function(test) {
    if (!test[1].comment) test[1].comment = test[0];

    it(test[1].comment, {
      metadata: {
        requires: { topology: ['single'] }
      },
      test: function(done) {
        parse(test[1].uri, function(err, object) {
          if (test[1].error) {
            expect(err).to.exist;
            expect(object).to.not.exist;
          } else {
            expect(err).to.be.null;
            expect(object).to.exist;
          }
          done();
        });
      }
    });
  });
});
<commit_msg>fix(dns txt records): check options are set<commit_after>'use strict';

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

var parse = require('../../lib/url_parser');
var expect = require('chai').expect;

// ./node_modules/.bin/mongodb-test-runner -l test/functional/dns_txt_records_tests.js

function getTests() {
  return fs
    .readdirSync(path.join(__dirname, 'specs/dns-txt-records'))
    .filter(x => x.indexOf('json') !== -1)
    .map(x => [x, fs.readFileSync(path.join(__dirname, 'specs/dns-txt-records', x), 'utf8')])
    .map(x => [path.basename(x[0], '.json'), JSON.parse(x[1])]);
}

describe('DNS and TXT record tests', function() {
  getTests().forEach(function(test) {
    if (!test[1].comment) test[1].comment = test[0];

    it(test[1].comment, {
      metadata: {
        requires: { topology: ['single'] }
      },
      test: function(done) {
        parse(test[1].uri, function(err, object) {
          if (test[1].error) {
            expect(err).to.exist;
            expect(object).to.not.exist;
          } else {
            expect(err).to.be.null;
            expect(object).to.exist;
            if (test[1].options && test[1].options.replicaSet) {
              expect(object.rs_options.rs_name).to.equal(test[1].options.replicaSet);
            }
            if (test[1].options && test[1].options.ssl) {
              expect(object.server_options.ssl).to.equal(test[1].options.ssl);
            }
          }
          done();
        });
      }
    });
  });
});
<|endoftext|>


<commit_before>const elementStyle = require('./element.js');

const sbgnShapes = require('./glyph');
const sbgnDimensions = require('./dimensions');

const isMultimer = require('./util/sbgn.js').isMultimer;
const hasAuxItems = require('./util/sbgn.js').hasAuxItems;

var sbgnStyleSheet = function (cytoscape) {

  return cytoscape.stylesheet()
        // general node style
        .selector('node')
        .css({
          'shape': (node) => elementStyle.sbgnShape(node),
          'content': (node) => elementStyle.sbgnContent(node),
          'font-size': (node) => elementStyle.labelTextSize(node),
          'text-valign': 'center',
          'text-halign': 'center',
          'border-width': 1.5,
          'border-color': '#555',
          'background-color': '#f6f6f6',
          'background-opacity': 0.5,
          'text-opacity': 1,
          'opacity': 1
        })
        .selector('node:selected')
        .css({
          'background-color': '#d67614',
          'target-arrow-color': '#000',
          'text-outline-color': '#000'
        })
        .selector('node:active')
        .css({
          'background-opacity': 0.7, 'overlay-color': '#d67614',
          'overlay-padding': '14'
        })

        // every process/entity pool node needs these properties
        .selector(`
          node[class="process"], node[class="uncertain process"], node[class="omitted process"],
          node[class="association"], node[class="dissociation"],
          node[class="phenotype"],
          node[class="source and sink"],
          node[class="perturbing agent"],
          node[class="unspecified entity"],
          node[class="nucleic acid feature"], node[class="nucleic acid feature multimer"],
          node[class="macromolecule"], node[class="macromolecule multimer"],
          node[class="simple chemical"], node[class="simple chemical multimer"]
        `)
        .css({
          'background-image': (node) => sbgnShapes.draw(node),
          'width': (node) => sbgnDimensions.width(node),
          'height': (node) => sbgnDimensions.height(node),
          'background-fit': 'none',
          'background-width': '100%',
          'background-height': '100%',
          'background-clip': 'none',
          'background-repeat': 'no-repeat',
          'border-width': 0,
        })

        // process node specific style
        .selector('node[class="association"], node[class="dissociation"]')
        .css({
          'background-opacity': 1
        })
        .selector('node[class="association"]')
        .css({
          'background-color': '#6B6B6B'
        })

        // entity pool node specific styles
        .selector('node[class="source and sink"]')
        .css({
          'shape-polygon-points': '-0.86, 0.5, -0.75, 0.65, -1, 0.95, -0.95, 1, -0.65, 0.75, -0.5, 0.86, 0, 1, 0.5, 0.86, 0.71, 0.71, 0.86, 0.5, 1, 0, 0.86, -0.5, 0.75, -0.65, 1, -0.95, 0.95, -1, 0.65, -0.75, 0.5, -0.86, 0, -1, -0.5, -0.86, -0.71, -0.71, -0.86, -0.5, -1, 0',
        })
        .selector('node[class="tag"]')
        .css({
          'width': (node) => sbgnDimensions.width(node),
          'height': (node) => sbgnDimensions.height(node),
          'shape-polygon-points': '-1, -1,   0.25, -1,   1, 0,    0.25, 1,    -1, 1'
        })
        .selector('node[class="perturbing agent"]')
        .css({
          'shape-polygon-points': '-1, -0.95, -0.75, 0, -1, 0.95, 1, 0.95, 0.75, 0, 1, -0.95',
        })

        // entity pool nodes that have one or more of (units of information, state variables, multimer)
        .selector(`
          node[class="nucleic acid feature"], node[class="nucleic acid feature multimer"],
          node[class="macromolecule"], node[class="macromolecule multimer"],
          node[class="simple chemical"], node[class="simple chemical multimer"],
          node[class="perturbing agent"]
        `)
        .css({
          'padding': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? 5 : 0,
          'background-width': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? '104%' : '100%',
          'background-height': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? '104%' : '100%',
        })

        // compound node specific style
        .selector('node[class="complex"], node[class="complex multimer"], node[class="compartment"]')
        .css({
          'border-width': 4,
          'compound-sizing-wrt-labels': 'exclude',
          'background-opacity': .2,
          'text-valign': 'bottom',
          'text-halign': 'center',
          // 'min-width': (node) => sbgnDimensions.width(node),
          'min-height': (node) => sbgnDimensions.height(node),
          // 'min-height-bias-bottom': '85%',
          // 'min-height-bias-top': '15%',
        })

        .selector('node[class="complex"], node[class="complex multimer"]')
        .css({
          'background-image': (node) => sbgnShapes.draw(node),
          'background-width': ['100%', '100%', '100%'],
          'background-position-x': ['0%', '0%', '0%', '25%', '88%'],          // order: line, line, clonemarker, uinfo, svar
          'background-position-y': ['100%', '38px', '100%', '0%', '0%'],
          'background-fit': ['contain', 'contain', 'none', 'none'],
          'background-clip': 'node',
          'padding': '16%',
          'padding-relative-to': 'max'
        })

        .selector('node[class="compartment"]')
        .css({
          'background-image': (node) => sbgnShapes.draw(node), // cache this
          'background-width': ['100%'],
          'background-position-x': ['0%', '25%'],          // order: line, line, uinfo
          'background-position-y': ['38px', '0%'],
          'background-fit': ['contain', 'none'],
          'background-clip': 'node',
          'padding': '16%',
          'padding-relative-to': 'max'
        })

        .selector('node[class="complex"], node[class="complex multimer"]')
        .css({
          // function that generates the bg image and properties
          // 'background-image': (node) => sbgnShapes.draw(node).images, // generate img and img properties
          // 'background-width': (node) => sbgnShapes.draw(node).widths
          // 'background-height': (node) => sbgnShapes.draw(node).heights
          // 'background-position-x': (node) => sbgnShapes.draw(node).xPositions
          // 'background-position-y': (node) => sbgnShapes.draw(node).yPositions
          // 'background-fit': (node) => sbgnShapes.draw(node).imgFits
          // 'background-clip': (node) => sbgnShapes.draw(node).imgClips
        })

        .selector('node[class="compartment"]')
        .css({
          'padding': '5%',
          'padding-relative-to': 'average',
        })

        // edge styling
        .selector('edge')
        .css({
          'curve-style': 'bezier',
          'line-color': '#555',
          'target-arrow-fill': 'hollow',
          'source-arrow-fill': 'hollow',
          'width': 1.5,
          'target-arrow-color': '#555',
          'source-arrow-color': '#555',
          'text-border-color': '#555',
          'color': '#555'
        })
        .selector('edge:selected')
        .css({
          'color': '#d67614',
          'line-color': '#d67614',
          'text-border-color': '#d67614',
          'source-arrow-color': '#d67614',
          'target-arrow-color': '#d67614'
        })
        .selector('edge:active')
        .css({
          'background-opacity': 0.7, 'overlay-color': '#d67614',
          'overlay-padding': '8'
        })
        .selector('edge[cardinality > 0]')
        .css({
          'text-rotation': 'autorotate',
          'text-background-shape': 'rectangle',
          'text-border-opacity': '1',
          'text-border-width': '1',
          'text-background-color': 'white',
          'text-background-opacity': '1'
        })
        .selector('edge[class="consumption"][cardinality > 0], edge[class="production"][cardinality > 0]')
        .css({
          'source-label': (edge) => '' + edge.data('cardinality'),
          'source-text-margin-y': '-10',
          'source-text-offset': (edge) => elementStyle.cardinalityDistance(edge)
        })
        .selector('edge[class]')
        .css({
          'target-arrow-shape': (edge) => elementStyle.sbgnArrowShape(edge),
          'source-arrow-shape': 'none'
        })
        .selector('edge[class="inhibition"]')
        .css({
          'target-arrow-fill': 'filled'
        })
        .selector('edge[class="production"]')
        .css({
          'target-arrow-fill': 'filled'
        })

        // core
        .selector('core')
        .css({
          'selection-box-color': '#d67614',
          'selection-box-opacity': '0.2', 'selection-box-border-color': '#d67614'
        });
};

module.exports = sbgnStyleSheet;
<commit_msg>use the arrow-scale property to increase arrow size - arrow heads are now large enough to `be seen by humans<commit_after>const elementStyle = require('./element.js');

const sbgnShapes = require('./glyph');
const sbgnDimensions = require('./dimensions');

const isMultimer = require('./util/sbgn.js').isMultimer;
const hasAuxItems = require('./util/sbgn.js').hasAuxItems;

var sbgnStyleSheet = function (cytoscape) {

  return cytoscape.stylesheet()
        // general node style
        .selector('node')
        .css({
          'shape': (node) => elementStyle.sbgnShape(node),
          'content': (node) => elementStyle.sbgnContent(node),
          'font-size': (node) => elementStyle.labelTextSize(node),
          'text-valign': 'center',
          'text-halign': 'center',
          'border-width': 1.5,
          'border-color': '#555',
          'background-color': '#f6f6f6',
          'background-opacity': 0.5,
          'text-opacity': 1,
          'opacity': 1
        })
        .selector('node:selected')
        .css({
          'background-color': '#d67614',
          'target-arrow-color': '#000',
          'text-outline-color': '#000'
        })
        .selector('node:active')
        .css({
          'background-opacity': 0.7, 'overlay-color': '#d67614',
          'overlay-padding': '14'
        })

        // every process/entity pool node needs these properties
        .selector(`
          node[class="process"], node[class="uncertain process"], node[class="omitted process"],
          node[class="association"], node[class="dissociation"],
          node[class="phenotype"],
          node[class="source and sink"],
          node[class="perturbing agent"],
          node[class="unspecified entity"],
          node[class="nucleic acid feature"], node[class="nucleic acid feature multimer"],
          node[class="macromolecule"], node[class="macromolecule multimer"],
          node[class="simple chemical"], node[class="simple chemical multimer"]
        `)
        .css({
          'background-image': (node) => sbgnShapes.draw(node),
          'width': (node) => sbgnDimensions.width(node),
          'height': (node) => sbgnDimensions.height(node),
          'background-fit': 'none',
          'background-width': '100%',
          'background-height': '100%',
          'background-clip': 'none',
          'background-repeat': 'no-repeat',
          'border-width': 0,
        })

        // process node specific style
        .selector('node[class="association"], node[class="dissociation"]')
        .css({
          'background-opacity': 1
        })
        .selector('node[class="association"]')
        .css({
          'background-color': '#6B6B6B'
        })

        // entity pool node specific styles
        .selector('node[class="source and sink"]')
        .css({
          'shape-polygon-points': '-0.86, 0.5, -0.75, 0.65, -1, 0.95, -0.95, 1, -0.65, 0.75, -0.5, 0.86, 0, 1, 0.5, 0.86, 0.71, 0.71, 0.86, 0.5, 1, 0, 0.86, -0.5, 0.75, -0.65, 1, -0.95, 0.95, -1, 0.65, -0.75, 0.5, -0.86, 0, -1, -0.5, -0.86, -0.71, -0.71, -0.86, -0.5, -1, 0',
        })
        .selector('node[class="tag"]')
        .css({
          'width': (node) => sbgnDimensions.width(node),
          'height': (node) => sbgnDimensions.height(node),
          'shape-polygon-points': '-1, -1,   0.25, -1,   1, 0,    0.25, 1,    -1, 1'
        })
        .selector('node[class="perturbing agent"]')
        .css({
          'shape-polygon-points': '-1, -0.95, -0.75, 0, -1, 0.95, 1, 0.95, 0.75, 0, 1, -0.95',
        })

        // entity pool nodes that have one or more of (units of information, state variables, multimer)
        .selector(`
          node[class="nucleic acid feature"], node[class="nucleic acid feature multimer"],
          node[class="macromolecule"], node[class="macromolecule multimer"],
          node[class="simple chemical"], node[class="simple chemical multimer"],
          node[class="perturbing agent"]
        `)
        .css({
          'padding': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? 5 : 0,
          'background-width': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? '104%' : '100%',
          'background-height': (node) =>  (isMultimer(node) || hasAuxItems(node)) ? '104%' : '100%',
        })

        // compound node specific style
        .selector('node[class="complex"], node[class="complex multimer"], node[class="compartment"]')
        .css({
          'border-width': 4,
          'compound-sizing-wrt-labels': 'exclude',
          'background-opacity': .2,
          'text-valign': 'bottom',
          'text-halign': 'center',
          // 'min-width': (node) => sbgnDimensions.width(node),
          'min-height': (node) => sbgnDimensions.height(node),
          // 'min-height-bias-bottom': '85%',
          // 'min-height-bias-top': '15%',
        })

        .selector('node[class="complex"], node[class="complex multimer"]')
        .css({
          'background-image': (node) => sbgnShapes.draw(node),
          'background-width': ['100%', '100%', '100%'],
          'background-position-x': ['0%', '0%', '0%', '25%', '88%'],          // order: line, line, clonemarker, uinfo, svar
          'background-position-y': ['100%', '38px', '100%', '0%', '0%'],
          'background-fit': ['contain', 'contain', 'none', 'none'],
          'background-clip': 'node',
          'padding': '16%',
          'padding-relative-to': 'max'
        })

        .selector('node[class="compartment"]')
        .css({
          'background-image': (node) => sbgnShapes.draw(node), // cache this
          'background-width': ['100%'],
          'background-position-x': ['0%', '25%'],          // order: line, line, uinfo
          'background-position-y': ['38px', '0%'],
          'background-fit': ['contain', 'none'],
          'background-clip': 'node',
          'padding': '16%',
          'padding-relative-to': 'max'
        })

        .selector('node[class="complex"], node[class="complex multimer"]')
        .css({
          // function that generates the bg image and properties
          // 'background-image': (node) => sbgnShapes.draw(node).images, // generate img and img properties
          // 'background-width': (node) => sbgnShapes.draw(node).widths
          // 'background-height': (node) => sbgnShapes.draw(node).heights
          // 'background-position-x': (node) => sbgnShapes.draw(node).xPositions
          // 'background-position-y': (node) => sbgnShapes.draw(node).yPositions
          // 'background-fit': (node) => sbgnShapes.draw(node).imgFits
          // 'background-clip': (node) => sbgnShapes.draw(node).imgClips
        })

        .selector('node[class="compartment"]')
        .css({
          'padding': '5%',
          'padding-relative-to': 'average',
        })

        // edge styling
        .selector('edge')
        .css({
          'arrow-scale': 1.75,
          'curve-style': 'bezier',
          'line-color': '#555',
          'target-arrow-fill': 'hollow',
          'source-arrow-fill': 'hollow',
          'width': 1.5,
          'target-arrow-color': '#555',
          'source-arrow-color': '#555',
          'text-border-color': '#555',
          'color': '#555'
        })
        .selector('edge:selected')
        .css({
          'color': '#d67614',
          'line-color': '#d67614',
          'text-border-color': '#d67614',
          'source-arrow-color': '#d67614',
          'target-arrow-color': '#d67614'
        })
        .selector('edge:active')
        .css({
          'background-opacity': 0.7, 'overlay-color': '#d67614',
          'overlay-padding': '8'
        })
        .selector('edge[cardinality > 0]')
        .css({
          'text-rotation': 'autorotate',
          'text-background-shape': 'rectangle',
          'text-border-opacity': '1',
          'text-border-width': '1',
          'text-background-color': 'white',
          'text-background-opacity': '1'
        })
        .selector('edge[class="consumption"][cardinality > 0], edge[class="production"][cardinality > 0]')
        .css({
          'source-label': (edge) => '' + edge.data('cardinality'),
          'source-text-margin-y': '-10',
          'source-text-offset': (edge) => elementStyle.cardinalityDistance(edge)
        })
        .selector('edge[class]')
        .css({
          'target-arrow-shape': (edge) => elementStyle.sbgnArrowShape(edge),
          'source-arrow-shape': 'none'
        })
        .selector('edge[class="inhibition"]')
        .css({
          'target-arrow-fill': 'filled'
        })
        .selector('edge[class="production"]')
        .css({
          'target-arrow-fill': 'filled'
        })

        // core
        .selector('core')
        .css({
          'selection-box-color': '#d67614',
          'selection-box-opacity': '0.2', 'selection-box-border-color': '#d67614'
        });
};

module.exports = sbgnStyleSheet;
<|endoftext|>