<commit_before>import {
  name as LIB_NAME,
  version as LIB_VERSION
} from '../../package.json';

const {
  toString
} = Object.prototype;

function _isBasicObject(val) {
  return typeof val === 'object' &&
    val !== null &&
    val.__proto__ === undefined;
}

function _argsStr(count, name = 'arg') {
  let names = [];

  for (let i = 0; i < count; i++) {
    names.push(`${name}${i + 1}`);
  }

  return names.join(', ');
}

function typeStr(val, k = undefined) {
  let t = (_isBasicObject(val)) ?
    'BasicObject' :
    toString.call(val).match(/^\[object ([^\]]*)\]$/)[1];

  if (t === 'Object') {
    if (val.constructor && (
      (val.constructor.name && val.constructor.name !== t)
    )) {
      t = val.constructor.name;
    }
  }

  if (val instanceof Function) {
    if (val.name && val.name !== t && (
      val.name.match(/^[A-Z]/) ||
      (k &&
        ['__apivis__chain_link',
          'constructor',
          'prototype',
          '__proto__'
        ].includes(k)
      )
    )) {
      t = val.name;
    }

    t = `${t}(${_argsStr(val.length)})`;
  }

  if (val && (
    (val.hasOwnProperty && val.hasOwnProperty('constructor'))
  )) {
    if (!t.endsWith('Prototype') && (
      (t !== 'Object' || val === Object.prototype)
    )) {
      t = `${t}.prototype`;
    }
  }

  if (val instanceof Error) {
    if (val.message) {
      t = `${t}("${val.message}")`;
    }
  }

  return t;
}

function descStr(val, k) {
  if (val === undefined || val === null) {
    return 'n/a';
  }

  let desc = Object.getOwnPropertyDescriptor(val, k);
  let d1 = '';
  let d2 = '';

  if (desc === undefined) {
    return 'n/a';
  }

  if (desc.hasOwnProperty('value')) { d1 += 'v'; }
  if (desc.writable) { d1 += 'w'; }
  if (desc.get) { d1 += 'g'; }
  if (desc.set) { d1 += 's'; }
  if (desc.enumerable) { d2 += 'e'; }
  if (desc.configurable) { d2 += 'c'; }

  return (d2) ?
    `${d1} ${d2}` :
    d1;
}

const _compare = (a, b) =>
  String(a).localeCompare(String(b), undefined, {numeric: true});
const _keys = (val, kind) =>
  (val === undefined || val === null) ?
    [] :
    Object[`getOwnProperty${kind}`](val).sort(_compare);
const _symbols = val => _keys(val, 'Symbols');
const _names = val => _keys(val, 'Names');

const members = val => _symbols(val).concat(_names(val));

function membersStr(val, indent = '  ', level = 0, leaf = val) {
  return members(val).
    map(k => {
      // Do not attempt to resolve these
      let skip = [
        'arguments',
        'callee',
        'caller'
      ];
      // Only resolve these in the context of leaf
      let leafOnly = [
        '__proto__'
      ];
      let v;
      let sv = '';
      let smax = 101;

      // First resolve k in the context of leaf (like it would be normally)
      try {
        if (!skip.includes(k)) {
          v = leaf[k];
        }
      } catch (err) {
        v = err; // Make the error visible in the dump
      }

      // Then try resolving k in the context of val (reached through
      // following __proto__) to eventually get a shadowed value (some
      // props only make sense when resolved in the context of leaf
      // and an exception will be thrown upon trying to access them through val)
      try {
        if ( !(val === leaf || leafOnly.includes(k) || skip.includes(k)) ) {
          v = val[k];
        }
      } catch (err) {
        // Leave v as set by trying to resolve k in the context of leaf
      }

      // Show the values of primitive booleans, numbers and strings
      switch (typeof v) {
      case 'boolean':
      case 'number':
        sv = `(${v})`;

        break;
      case 'string':
        sv = `(${JSON.stringify(v)})`;

        break;
      }

      return `${indent.repeat(level)}${String(k)}{${descStr(val, k)}}: ${typeStr(v, k)}${sv}`;
    }).
    join('\n');
}

function chain(val) {
  let links = [val];

  for (let link = Object.getPrototypeOf(val);
    link;
    link = Object.getPrototypeOf(link)
  ) {
    links.push(link);
  }

  return links;
}

function chainStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]`).
    join('\n');
}

function apiStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]\n${membersStr(v, indent, i + 1, val)}`).
    join('\n');
}

// peek42 plugin
function peek42(fnOutput, fnComment) {
  return {
    type(val, comment = undefined, opts = undefined) {
      fnOutput(
        typeStr(val),
        fnComment(comment, val, 'type'),
        opts
      );
    },
    desc(val, k, comment = undefined, opts = undefined) {
      fnOutput(
        descStr(val, k),
        fnComment(comment, `${String(k)} in ${typeStr(val)}`, 'desc'),
        opts
      );
    },
    members(val, comment = undefined, opts = undefined) {
      fnOutput(
        membersStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined,
          (opts && typeof opts.indentLevel === 'number') ?
            opts.indentLevel :
            undefined
        ),
        fnComment(comment, typeStr(val), 'members'),
        opts
      );
    },
    chain(val, comment = undefined, opts = undefined) {
      fnOutput(
        chainStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'chain'),
        opts
      );
    },
    api(val, comment = undefined, opts = undefined) {
      fnOutput(
        apiStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'api'),
        opts
      );
    }
  };
}

const apivis = {
  get [Symbol.toStringTag]() {
    return LIB_NAME;
  },
  version: LIB_VERSION,
  typeStr,
  descStr,
  members,
  membersStr,
  chain,
  chainStr,
  apiStr,
  peek42
};

export {typeStr, descStr, members, membersStr, chain, chainStr, apiStr};
export default apivis;
<commit_msg>Show date values and array lengths<commit_after>import {
  name as LIB_NAME,
  version as LIB_VERSION
} from '../../package.json';

const {
  toString
} = Object.prototype;

function _isBasicObject(val) {
  return typeof val === 'object' &&
    val !== null &&
    val.__proto__ === undefined;
}

function _argsStr(count, name = 'arg') {
  let names = [];

  for (let i = 0; i < count; i++) {
    names.push(`${name}${i + 1}`);
  }

  return names.join(', ');
}

function typeStr(val, k = undefined) {
  let t = (_isBasicObject(val)) ?
    'BasicObject' :
    toString.call(val).match(/^\[object ([^\]]*)\]$/)[1];

  if (t === 'Object') {
    if (val.constructor && (
      (val.constructor.name && val.constructor.name !== t)
    )) {
      t = val.constructor.name;
    }
  }

  if (val instanceof Function) {
    if (val.name && val.name !== t && (
      val.name.match(/^[A-Z]/) ||
      (k &&
        ['__apivis__chain_link',
          'constructor',
          'prototype',
          '__proto__'
        ].includes(k)
      )
    )) {
      t = val.name;
    }

    t = `${t}(${_argsStr(val.length)})`;
  }

  if (val && (
    (val.hasOwnProperty && val.hasOwnProperty('constructor'))
  )) {
    if (!t.endsWith('Prototype') && (
      (t !== 'Object' || val === Object.prototype)
    )) {
      t = `${t}.prototype`;
    }
  }

  if (val instanceof Error) {
    if (val.message) {
      t = `${t}("${val.message}")`;
    }
  }

  return t;
}

function descStr(val, k) {
  if (val === undefined || val === null) {
    return 'n/a';
  }

  let desc = Object.getOwnPropertyDescriptor(val, k);
  let d1 = '';
  let d2 = '';

  if (desc === undefined) {
    return 'n/a';
  }

  if (desc.hasOwnProperty('value')) { d1 += 'v'; }
  if (desc.writable) { d1 += 'w'; }
  if (desc.get) { d1 += 'g'; }
  if (desc.set) { d1 += 's'; }
  if (desc.enumerable) { d2 += 'e'; }
  if (desc.configurable) { d2 += 'c'; }

  return (d2) ?
    `${d1} ${d2}` :
    d1;
}

const _compare = (a, b) =>
  String(a).localeCompare(String(b), undefined, {numeric: true});
const _keys = (val, kind) =>
  (val === undefined || val === null) ?
    [] :
    Object[`getOwnProperty${kind}`](val).sort(_compare);
const _symbols = val => _keys(val, 'Symbols');
const _names = val => _keys(val, 'Names');

const members = val => _symbols(val).concat(_names(val));

function membersStr(val, indent = '  ', level = 0, leaf = val) {
  return members(val).
    map(k => {
      // Do not attempt to resolve these
      let skip = [
        'arguments',
        'callee',
        'caller'
      ];
      // Only resolve these in the context of leaf
      let leafOnly = [
        '__proto__'
      ];
      let v;
      let sv = '';
      let smax = 101;

      // First resolve k in the context of leaf (like it would be normally)
      try {
        if (!skip.includes(k)) {
          v = leaf[k];
        }
      } catch (err) {
        v = err; // Make the error visible in the dump
      }

      // Then try resolving k in the context of val (reached through
      // following __proto__) to eventually get a shadowed value (some
      // props only make sense when resolved in the context of leaf
      // and an exception will be thrown upon trying to access them through val)
      try {
        if ( !(val === leaf || leafOnly.includes(k) || skip.includes(k)) ) {
          v = val[k];
        }
      } catch (err) {
        // Leave v as set by trying to resolve k in the context of leaf
      }

      // Show select values
      switch (typeof v) {
      case 'boolean':
      case 'number':
        sv = `(${v})`;

        break;
      case 'string':
        sv = `(${JSON.stringify(v)})`;

        break;
      case 'object':
        if (v instanceof Date) {
          sv = `(${JSON.stringify(v)})`;
        } else if (Array.isArray(v)) {
          sv = `(${v.length})`;
        }

        break;
      }

      return `${indent.repeat(level)}${String(k)}{${descStr(val, k)}}: ${typeStr(v, k)}${sv}`;
    }).
    join('\n');
}

function chain(val) {
  let links = [val];

  for (let link = Object.getPrototypeOf(val);
    link;
    link = Object.getPrototypeOf(link)
  ) {
    links.push(link);
  }

  return links;
}

function chainStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]`).
    join('\n');
}

function apiStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]\n${membersStr(v, indent, i + 1, val)}`).
    join('\n');
}

// peek42 plugin
function peek42(fnOutput, fnComment) {
  return {
    type(val, comment = undefined, opts = undefined) {
      fnOutput(
        typeStr(val),
        fnComment(comment, val, 'type'),
        opts
      );
    },
    desc(val, k, comment = undefined, opts = undefined) {
      fnOutput(
        descStr(val, k),
        fnComment(comment, `${String(k)} in ${typeStr(val)}`, 'desc'),
        opts
      );
    },
    members(val, comment = undefined, opts = undefined) {
      fnOutput(
        membersStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined,
          (opts && typeof opts.indentLevel === 'number') ?
            opts.indentLevel :
            undefined
        ),
        fnComment(comment, typeStr(val), 'members'),
        opts
      );
    },
    chain(val, comment = undefined, opts = undefined) {
      fnOutput(
        chainStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'chain'),
        opts
      );
    },
    api(val, comment = undefined, opts = undefined) {
      fnOutput(
        apiStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'api'),
        opts
      );
    }
  };
}

const apivis = {
  get [Symbol.toStringTag]() {
    return LIB_NAME;
  },
  version: LIB_VERSION,
  typeStr,
  descStr,
  members,
  membersStr,
  chain,
  chainStr,
  apiStr,
  peek42
};

export {typeStr, descStr, members, membersStr, chain, chainStr, apiStr};
export default apivis;
<|endoftext|>


<commit_before>/*jslint browser: true, undef: true*//*global Ext*/

/**
 * @abstract
 * An abstract class for singletons that facilitates communication with backend services on a local or remote emergence server
 */
Ext.define('Emergence.util.AbstractAPI', {
    extend: 'Jarvus.util.AbstractAPI',

    config: {
        sessionData: null
    },

    /**
     * @event
     * Fires after successful login
     * @param {Object} sessionData
     */

    buildHeaders: function(headers) {
        headers = headers || {};

        if (!('Accept' in headers)) {
            headers.Accept = 'application/json';
        }

        return headers;
    },

    /**
     * Attempt to load session data
     * @param {String} hostname
     * @param {String} username
     * @param {String} password
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    getSessionData: function(callback, scope) {
        var me = this;

        me.request({
            url: '/login',
            method: 'GET',
            success: function(response) {
                if(response.data && response.data.success) {
                    me.setSessionData(response.data.data);
                    Ext.callback(callback, scope, [true, response]);
                    me.fireEvent('login', response.data.data);
                }
                else {
                    Ext.callback(callback, scope, [false, response]);
                }
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Login to a remote Slate instance
     * @param {String} hostname
     * @param {String} username
     * @param {String} password
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    login: function(username, password, callback, scope) {
        var me = this;

        me.request({
            url: '/login',
            params: {
                '_LOGIN[username]': username,
                '_LOGIN[password]': password,
                '_LOGIN[returnMethod]': 'POST'
            },
            success: function(response) {
                if (response.data && response.data.success) {
                    me.setSessionData(response.data.data);
                    Ext.callback(callback, scope, [true, response]);
                    me.fireEvent('login', response.data.data);
                } else {
                    Ext.callback(callback, scope, [false, response]);
                }
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Logout from remote Slate instance
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    logout: function(callback, scope) {
        this.request({
            url: '/login/logout',
            success: function(response) {
                Ext.callback(callback, scope, [true, response]);
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Upload an HTML5 file object
     * @param {Object} the html5 file object
     * @param {Function} the function to call after the response
     * @param {Object} the scope for the callback function
     */
    uploadMedia: function(file, callback, scope) {
        var me = this;
        var formData = new FormData();

        formData.append('mediaFile', file);

        me.request({
            method: 'POST',
            url: '/media/upload',
            headers: {
                // Setting Content-Type to null allows the browser to automatically set Content-Type.
                // Must-have for file uploads using the FormData object.
                'Content-Type': null
            },
            rawData: formData,
            success: function(response) {
                var success = response.data && response.data.success,
                    mediaData = success && response.data.data;

                Ext.callback(callback, scope, [success, response, mediaData]);
            }
        });
    }
});<commit_msg>Rename getSessionData method to avoid conflict with config getter<commit_after>/*jslint browser: true, undef: true*//*global Ext*/

/**
 * @abstract
 * An abstract class for singletons that facilitates communication with backend services on a local or remote emergence server
 */
Ext.define('Emergence.util.AbstractAPI', {
    extend: 'Jarvus.util.AbstractAPI',

    config: {
        sessionData: null
    },

    /**
     * @event
     * Fires after successful login
     * @param {Object} sessionData
     */

    buildHeaders: function(headers) {
        headers = headers || {};

        if (!('Accept' in headers)) {
            headers.Accept = 'application/json';
        }

        return headers;
    },

    /**
     * Attempt to load session data
     * @param {String} hostname
     * @param {String} username
     * @param {String} password
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    loadSessionData: function(callback, scope) {
        var me = this;

        me.request({
            url: '/login',
            method: 'GET',
            success: function(response) {
                if(response.data && response.data.success) {
                    me.setSessionData(response.data.data);
                    Ext.callback(callback, scope, [true, response]);
                    me.fireEvent('login', response.data.data);
                }
                else {
                    Ext.callback(callback, scope, [false, response]);
                }
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Login to a remote Slate instance
     * @param {String} hostname
     * @param {String} username
     * @param {String} password
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    login: function(username, password, callback, scope) {
        var me = this;

        me.request({
            url: '/login',
            params: {
                '_LOGIN[username]': username,
                '_LOGIN[password]': password,
                '_LOGIN[returnMethod]': 'POST'
            },
            success: function(response) {
                if (response.data && response.data.success) {
                    me.setSessionData(response.data.data);
                    Ext.callback(callback, scope, [true, response]);
                    me.fireEvent('login', response.data.data);
                } else {
                    Ext.callback(callback, scope, [false, response]);
                }
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Logout from remote Slate instance
     * @param {Function} callback A function to call and pass the new client data to when it is available
     * @param {Object} scope Scope for the callback function
     */
    logout: function(callback, scope) {
        this.request({
            url: '/login/logout',
            success: function(response) {
                Ext.callback(callback, scope, [true, response]);
            },
            exception: function(response) {
                Ext.callback(callback, scope, [false, response]);
            }
        });
    },

    /**
     * Upload an HTML5 file object
     * @param {Object} the html5 file object
     * @param {Function} the function to call after the response
     * @param {Object} the scope for the callback function
     */
    uploadMedia: function(file, callback, scope) {
        var me = this;
        var formData = new FormData();

        formData.append('mediaFile', file);

        me.request({
            method: 'POST',
            url: '/media/upload',
            headers: {
                // Setting Content-Type to null allows the browser to automatically set Content-Type.
                // Must-have for file uploads using the FormData object.
                'Content-Type': null
            },
            rawData: formData,
            success: function(response) {
                var success = response.data && response.data.success,
                    mediaData = success && response.data.data;

                Ext.callback(callback, scope, [success, response, mediaData]);
            }
        });
    }
});<|endoftext|>


<commit_before>import {stripIndent} from 'common-tags'

export default {
  id: "api",
  title: "API",
  content: stripIndent`
    ## Core Addon API

    This is the core addon API. This is how to get the addon API:

    ~~~js
    import addonAPI from '@kadira/kadira/storybook-addons';
    ~~~

    Have a look at the API methods for more details:

    ### addonAPI.getChannel()

    Get an instance to the channel where you can communicate with the manager and the preview. You can find this in both the addon register code and in your addon’s wrapper component (where used inside a story).

    It has a NodeJS [EventEmitter](https://nodejs.org/api/events.html) compatible API. So, you can use it to emit events and listen for events.

    ### addonAPI.register()

    This method allows you to register an addon and get the storybook API. You can do this only in the Manager App.
    See how we can use this:

    ~~~js
    // Register the addon with a unique name.
    addonAPI.register('kadira/notes', (storybookAPI) => {

    });
    ~~~

    Now you'll get an instance to our StorybookAPI. See the [api docs](/docs/react-storybook/addons/api#storybook-api) for Storybook API regarding using that.

    ### addonAPI.addPanel()

    This method allows you to add a panel to Storybook. (Storybook's Action Logger is a panel). You can do this only in the Manager App.
    See how you can use this method:

    ~~~js
    const MyPanel = () => (

        This is a panel.

    );

    // give a unique name for the panel
    addonAPI.addPanel('kadira/notes/panel', {
      title: 'Notes',
      render: () => (
        <MyPanel />
      ),
    });
    ~~~

    As you can see, you can set any React Component as the panel. Currently, it's just a text. But you can do anything you want.

    You also pass the channel and the Storybook API into that. See:

    ~~~js
    addonAPI.register('kadira/notes', (storybookAPI) => {
      // Also need to set a unique name to the panel.
      addonAPI.addPanel('kadira/notes/panel', {
        title: 'Notes',
        render: () => (
          <Notes channel={addons.getChannel()} api={storybookAPI}/>
        ),
      })
    })
    ~~~

    ## Storybook API

    Storybook API allows you to access different functionalities of Storybook UI. You can move an instance to the Storybook API when you register an addon.

    Let's have a look at API methods.

    ### storybookAPI.selectStory()

    With this method, you can select a story via an API. This method accepts two parameters.

    1. story kind name
    2. story name (optional)

    Let's say you've got a story like this:

    ~~~js
    storiesOf('Button', module)
      .add('with text', () => (
        <Button onClick={action('clicked')}>Hello Button</Button>
      ));
    ~~~

    This is how you can select the above story:

    ~~~js
    storybookAPI.selectStory('Button', 'with text');
    ~~~

    ### storybookAPI.setQueryParams()

    This method allows you to set query string parameters. You can use that as temporary storage for addons. Here's how you set query params.

    ~~~js
    storybookAPI.setQueryParams({
      abc: 'this is abc',
      bbc: 'this is bbc',
    });
    ~~~

    > If you need to remove a query param, use \`null\` for that. For an example, let's say we need to remove bbc query param. This is how we do it:

    ~~~js
    storybookAPI.setQueryParams({
      bbc: null,
    });
    ~~~

    ### storybookAPI.getQueryParam()

    This method allows you to get a query param set by above API \`setQueryParams\`. For example, let's say we need to get the bbc query param. Then this how we do it:

    ~~~js
    storybookAPI.getQueryParam('bbc');
    ~~~

    ### storybookAPI.onStory(fn)

    This method allows you to register a handler function which will be called whenever the user navigates between stories.

    ~~~js
    storybookAPI.onStory((kind, story) => console.log(kind, story));
    ~~~
  `
};
<commit_msg>Fix wrong npm package path<commit_after>import {stripIndent} from 'common-tags'

export default {
  id: "api",
  title: "API",
  content: stripIndent`
    ## Core Addon API

    This is the core addon API. This is how to get the addon API:

    ~~~js
    import addonAPI from '@kadira/storybook-addons';
    ~~~

    Have a look at the API methods for more details:

    ### addonAPI.getChannel()

    Get an instance to the channel where you can communicate with the manager and the preview. You can find this in both the addon register code and in your addon’s wrapper component (where used inside a story).

    It has a NodeJS [EventEmitter](https://nodejs.org/api/events.html) compatible API. So, you can use it to emit events and listen for events.

    ### addonAPI.register()

    This method allows you to register an addon and get the storybook API. You can do this only in the Manager App.
    See how we can use this:

    ~~~js
    // Register the addon with a unique name.
    addonAPI.register('kadira/notes', (storybookAPI) => {

    });
    ~~~

    Now you'll get an instance to our StorybookAPI. See the [api docs](/docs/react-storybook/addons/api#storybook-api) for Storybook API regarding using that.

    ### addonAPI.addPanel()

    This method allows you to add a panel to Storybook. (Storybook's Action Logger is a panel). You can do this only in the Manager App.
    See how you can use this method:

    ~~~js
    const MyPanel = () => (

        This is a panel.

    );

    // give a unique name for the panel
    addonAPI.addPanel('kadira/notes/panel', {
      title: 'Notes',
      render: () => (
        <MyPanel />
      ),
    });
    ~~~

    As you can see, you can set any React Component as the panel. Currently, it's just a text. But you can do anything you want.

    You also pass the channel and the Storybook API into that. See:

    ~~~js
    addonAPI.register('kadira/notes', (storybookAPI) => {
      // Also need to set a unique name to the panel.
      addonAPI.addPanel('kadira/notes/panel', {
        title: 'Notes',
        render: () => (
          <Notes channel={addons.getChannel()} api={storybookAPI}/>
        ),
      })
    })
    ~~~

    ## Storybook API

    Storybook API allows you to access different functionalities of Storybook UI. You can move an instance to the Storybook API when you register an addon.

    Let's have a look at API methods.

    ### storybookAPI.selectStory()

    With this method, you can select a story via an API. This method accepts two parameters.

    1. story kind name
    2. story name (optional)

    Let's say you've got a story like this:

    ~~~js
    storiesOf('Button', module)
      .add('with text', () => (
        <Button onClick={action('clicked')}>Hello Button</Button>
      ));
    ~~~

    This is how you can select the above story:

    ~~~js
    storybookAPI.selectStory('Button', 'with text');
    ~~~

    ### storybookAPI.setQueryParams()

    This method allows you to set query string parameters. You can use that as temporary storage for addons. Here's how you set query params.

    ~~~js
    storybookAPI.setQueryParams({
      abc: 'this is abc',
      bbc: 'this is bbc',
    });
    ~~~

    > If you need to remove a query param, use \`null\` for that. For an example, let's say we need to remove bbc query param. This is how we do it:

    ~~~js
    storybookAPI.setQueryParams({
      bbc: null,
    });
    ~~~

    ### storybookAPI.getQueryParam()

    This method allows you to get a query param set by above API \`setQueryParams\`. For example, let's say we need to get the bbc query param. Then this how we do it:

    ~~~js
    storybookAPI.getQueryParam('bbc');
    ~~~

    ### storybookAPI.onStory(fn)

    This method allows you to register a handler function which will be called whenever the user navigates between stories.

    ~~~js
    storybookAPI.onStory((kind, story) => console.log(kind, story));
    ~~~
  `
};
<|endoftext|>


<commit_before>
/*
 * Copyright (c) Burak Arslan (burak.arslan-qx@arskom.com.tr).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Arskom Consultancy Ltd. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

qx.Class.define("soap.WsdlCache", {extend: qx.core.Object
    ,properties: {
         _name   : {check: "String"}
        ,_client : {check: "soap.Client"}
        ,_params : {check: "soap.Parameters"}
        ,_simple : {check: "Boolean", init:false}
    }

    ,construct: function(node) {
        var ctx = this;
        var get_elts = qx.xml.Element.getElementsByTagNameNS;
        var _ns_wsdl = "http://schemas.xmlsoap.org/wsdl/";

        ctx.methods = new Object();
        ctx.messages = new Array();
        ctx.schema = new Object();
        ctx.__target_namespace = node.documentElement.getAttribute(
                                                             "targetNamespace");
        ctx.__prefix_map = new Object();

        qx.log.Logger.debug("New service: " + ctx.__target_namespace);

        if (qx.core.Variant.isSet("qx.client", "mshtml")) {
            this.definitions = node.childNodes[1];
        }
        else {
            this.definitions = node.childNodes[0];
        }

        var cn = this.definitions.childNodes;

        var i,l,j,k,tn;
        var port_type_node = get_elts(node, _ns_wsdl, 'portType')[0];
        var types_node = get_elts(node, _ns_wsdl, 'types')[0];

        // fill methods
        var methods = ctx.methods;
        cn = port_type_node.childNodes;
        for (i=0, l=cn.length; i<l; ++i) {
            var method_name = cn[i].getAttribute("name");
            methods[method_name] = new Object();

            var method = methods[method_name];
            for (j=0, k=cn[i].childNodes.length; j<k; ++j) {
                var method_node = cn[i].childNodes[j];

                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    tn = method_node.baseName;
                }
                else {
                    tn = method_node.localName;
                }

                method.input = new Object();
                method.input.name = null;
                method.input.message = null;

                method.output = new Object();
                method.output.name = null;
                method.output.message = null;

                if (tn == "input" || tn == "output") {
                    method[tn] = new Object();
                    method[tn].name = method_node.getAttribute("name");
                    method[tn].message = method_node.getAttribute("message");
                }
            }
        }

        var schema_node = null;
        var n;
        for (i=0, l=types_node.childNodes.length; i<l; ++i) {
            schema_node = types_node.childNodes[i];
            var schema_tns = schema_node.getAttribute("targetNamespace");
            var schema_key = schema_tns;

            var schema = ctx.schema[schema_key];
            if (! schema) {
                ctx.schema[schema_key] = new Object();
                schema = ctx.schema[schema_key];
                schema.simple = new Object();
                schema.element = new Object();
                schema.complex = new Object();
            }

            cn = schema_node.childNodes;
            for (j=0, k = cn.length; j<k; ++j) {
                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    tn = cn[j].baseName;
                }
                else {
                    tn = cn[j].localName;
                }

                var elt = this.__type_from_node(cn[j], schema_tns);
                if (tn == "element") {
                    //schema.element[elt.name] = elt
                }
                else if (tn == "import") {

                }
                else if (tn == "simpleType") {
                    this.__decode_simple_type(cn[j],elt);
                }
                else if (tn == "complexType") {
                    this.__decode_complex_type(cn[j],elt);
                }
            }
        }
        // fill schema
        if (schema_node == null) {
            ctx.schema = null;
        }
    }

    ,members: {
         __cache: null
        ,__target_namespace : null
        ,methods : null
        ,messages : null
        ,schema : null
        ,definitions : null

        ,__decode_complex_type : function(node, elt) {
            elt.children = new Object();
            var first_node = node.childNodes[0];
            var child;

            if (first_node.hasChildNodes()) {
                first_node = first_node.childNodes[0];

                var min_occurs = first_node.getAttribute("minOccurs");
                var max_occurs = first_node.getAttribute("maxOccurs");
                if (first_node.nextSibling == null && min_occurs != null
                                                   && max_occurs != null) { // it's an array
                    elt.is_array = true;
                    elt.min_occurs = min_occurs;
                    elt.max_occurs = max_occurs;

                    child = this.__type_from_node(first_node);

                    elt.children[child.name] = child;
                    elt.children[0] = child;
                }
                else {
                    var order=0;
                    for (n=first_node; n!=null; n=n.nextSibling) {
                        child = this.__type_from_node(n);

                        elt.children[child.name] = child;
                        elt.children[order] = child;

                        ++order;
                    }
                }
            }

            this.schema[elt.ns].complex[elt.name] = elt
        }

        ,__decode_simple_type : function(node, elt) {
            this.schema[elt.ns].simple[elt.name] = elt

            for (var n = node.firstChild; n; n=n.nextSibling) {
                var nn;
                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    nn = n.baseName;
                }
                else {
                    nn = n.localName;
                }

                if (nn == 'restriction') {
                    elt.base = n.getAttribute("base");
                    elt.base_ns = this.type_qname_to_ns(n,elt.base);
                    elt.restrictions = new Object();
                    for (var r = n.firstChild; r != null; r=r.nextSibling) {
                        // TODO: fill restrictions
                    }
                }
            }
        }

        ,__type_from_node: function(node, ns) {
            var elt = new Object();

            elt.type = node.getAttribute("type");
            elt.name = node.getAttribute("name");
            if (ns) {
                elt.ns = ns;
            }

            if (elt.type) {
                elt.ns = this.type_qname_to_ns(node, elt.type);
            }
            else {
                elt.ns = node.parentNode.getAttribute("targetNamespace")
            }

            elt.base = null;

            return elt;
        }

        ,type_qname_to_ns: function(node, type_qname) {
            var type_defn = type_qname.split(":");
            var retval;

            if (type_defn.length > 0) {
                retval = this.__prefix_map[type_defn[0]];

                if (! retval) {
                    var tnode = node;
                    while (! retval) {
                        retval = tnode.getAttribute("xmlns:" + type_defn[0]);
                        tnode = tnode.parentNode;
                    }

                    if (retval) {
                        this.__prefix_map[type_defn[0]] = retval;
                    }
                }
            }

            return retval;
        }

        ,get_target_namespace: function() {
            return this.__target_namespace;
        }

        ,__get_simple_base : function(child) {
            var retval;
            var type_l = child.type.split(":")[1];
            var simple_type_ns = this.schema[child.ns]

            if (simple_type_ns) {
                var simple_type = simple_type_ns.simple[type_l];

                if (simple_type) {
                    while (simple_type.base != null) {
                        var base_ns = this.schema[simple_type.base_ns]
                        if (base_ns) {
                            var base_l = simple_type.base.split(":")[1];
                            simple_type = base_ns.simple[base_l];

                            qx.core.Assert.assertNotUndefined(simple_type,
                                    "Simple Type " +
                                    "'{" + simple_type.base_ns + "}'" +
                                    " '" + simple_type.base + "' " +
                                    "does not exist");
                        }
                        else {
                            base_ns = null;
                            break;
                        }
                    }

                    if (base_ns) {
                        retval = simple_type.type.split(":")[1];
                    }
                    else {
                        retval = simple_type.base.split(":")[1];
                    }

                    retval = soap.Client.TYPE_MAP[retval];
                }
            }

            return retval;
        }

        ,get_class_map: function(object_namespace, object_name) {
            var ctx=this;
            var retval;

            if (! object_namespace) {
                object_namespace = ctx.__target_namespace;
            }

            if (! object_name) {
                throw new Error("object_name must be defined!");
            }

            qx.log.Logger.debug("creating object: {" + object_namespace + "}"
                                                            + object_name + "");

            var schema = ctx.schema[object_namespace];
            if (! schema) {
                qx.log.Logger.debug("'" + object_namespace + "' not found!");
                return undefined;
            }

            var type = schema.complex[object_name];
            if (! type) {
                qx.log.Logger.debug("'" + object_name + "' not found!");
            }
            else {
                var children = type.children;
                retval = {
                    extend: qx.core.Object,
                    properties: {},
                    statics: {
                        TYPE_DEFINITION: type
                    }
                };

                // get the props
                var props = retval.properties;
                for (var k in children) {
                    var child = children[k];
                    var prop_name = "_" + child.name;
                    if ( (! (prop_name in props))
                                    && children.hasOwnProperty(k)
                                    && isNaN(k) ) {

                        var type_l = child.type.split(":")[1];

                        var prop_type;
                        if (child.is_array) {
                            prop_type = "Array";
                        }
                        else {
                            prop_type = soap.Client.TYPE_MAP[type_l];
                        }

                        if (! prop_type) {
                            prop_type = this.__get_simple_base(child);
                        }

                        if (! prop_type) {
                            prop_type = "Object";
                        }

                        var prop_def = {"check": prop_type, init: null,
                                                                 nullable: true}

                        qx.log.Logger.debug(object_name + "." + prop_name
                                                 + " is a '" + prop_type + "'");

                        props[prop_name] = prop_def;
                    }
                }
            }

            return retval;
        }

        ,get_class: function(object_namespace, object_name) {
            var ctx=this;

            if (! object_name) {
                throw new Error("object_name must be defined!");
            }

            var class_name = object_namespace + "." + object_name;
            var clazz = qx.Class.getByName(class_name);

            if (! clazz) {
                var class_map = this.get_class_map(object_namespace, object_name);
                if (class_map) {
                    clazz = qx.Class.define(class_name, class_map);
                }
            }

            return clazz;
        }

        ,get_object: function(object_namespace, object_name) {
            var clazz = this.get_class(object_namespace, object_name);
            var retval;

            if (clazz) {
                retval = new clazz();
            }

            return retval;
        }

        ,get_table: function(method_name) {
            // methodun dondurdugu veri tipini alır.
            var method_input = this.schema.complex[method_name];
            if (! method_input) {
                throw new Error("Method named '" + method_name +
                                                  "' is not exposed via wsdl.");
            }

            var class_map = {extend: arskom.ui.Table};
        }

        ,get_form: function(object_namespace, object_name) {
            var class_map = this.get_class_map(object_namespace, object_name);
            var props = class_map.properties;
            var form = new qx.ui.form.Form();
            var pd = this.self(arguments).PRIMITIVE_DEFAULTS;

            for (var key in props) {
                if (props.hasOwnProperty(key)) {
                    var name = key.slice(1);
                    var type = props[key].check;

                    if (type in pd) {
                        var wgt = new pd[type]();
                        form.add(wgt, name);
                    }
                }
            }

            return form;
        }

        ,get_form_widget: function(object_namespace, object_name) {
            var form = this.get_form(object_namespace, object_name);
            var retval = new qx.ui.form.renderer.Single(form);
            return retval;
        }
    }
});
<commit_msg>separated sequence decoding to its new function<commit_after>
/*
 * Copyright (c) Burak Arslan (burak.arslan-qx@arskom.com.tr).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Arskom Consultancy Ltd. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

qx.Class.define("soap.WsdlCache", {extend: qx.core.Object
    ,properties: {
         _name   : {check: "String"}
        ,_client : {check: "soap.Client"}
        ,_params : {check: "soap.Parameters"}
        ,_simple : {check: "Boolean", init:false}
    }

    ,construct: function(node) {
        var ctx = this;
        var get_elts = qx.xml.Element.getElementsByTagNameNS;
        var _ns_wsdl = "http://schemas.xmlsoap.org/wsdl/";

        ctx.methods = new Object();
        ctx.messages = new Array();
        ctx.schema = new Object();
        ctx.__target_namespace = node.documentElement.getAttribute(
                                                             "targetNamespace");
        ctx.__prefix_map = new Object();

        qx.log.Logger.debug("New service: " + ctx.__target_namespace);

        if (qx.core.Variant.isSet("qx.client", "mshtml")) {
            this.definitions = node.childNodes[1];
        }
        else {
            this.definitions = node.childNodes[0];
        }

        var cn = this.definitions.childNodes;

        var i,l,j,k,tn;
        var port_type_node = get_elts(node, _ns_wsdl, 'portType')[0];
        var types_node = get_elts(node, _ns_wsdl, 'types')[0];

        // fill methods
        var methods = ctx.methods;
        cn = port_type_node.childNodes;
        for (i=0, l=cn.length; i<l; ++i) {
            var method_name = cn[i].getAttribute("name");
            methods[method_name] = new Object();

            var method = methods[method_name];
            for (j=0, k=cn[i].childNodes.length; j<k; ++j) {
                var method_node = cn[i].childNodes[j];

                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    tn = method_node.baseName;
                }
                else {
                    tn = method_node.localName;
                }

                method.input = new Object();
                method.input.name = null;
                method.input.message = null;

                method.output = new Object();
                method.output.name = null;
                method.output.message = null;

                if (tn == "input" || tn == "output") {
                    method[tn] = new Object();
                    method[tn].name = method_node.getAttribute("name");
                    method[tn].message = method_node.getAttribute("message");
                }
            }
        }

        var schema_node = null;
        var n;
        for (i=0, l=types_node.childNodes.length; i<l; ++i) {
            schema_node = types_node.childNodes[i];
            var schema_tns = schema_node.getAttribute("targetNamespace");
            var schema_key = schema_tns;

            var schema = ctx.schema[schema_key];
            if (! schema) {
                ctx.schema[schema_key] = new Object();
                schema = ctx.schema[schema_key];
                schema.simple = new Object();
                schema.element = new Object();
                schema.complex = new Object();
            }

            cn = schema_node.childNodes;
            for (j=0, k = cn.length; j<k; ++j) {
                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    tn = cn[j].baseName;
                }
                else {
                    tn = cn[j].localName;
                }

                var elt = this.__type_from_node(cn[j], schema_tns);
                if (tn == "element") {
                    //schema.element[elt.name] = elt
                }
                else if (tn == "import") {

                }
                else if (tn == "simpleType") {
                    this.__decode_simple_type(cn[j],elt);
                }
                else if (tn == "complexType") {
                    this.__decode_complex_type(cn[j],elt);
                }
            }
        }
        // fill schema
        if (schema_node == null) {
            ctx.schema = null;
        }
    }

    ,members: {
         __cache: null
        ,__target_namespace : null
        ,methods : null
        ,messages : null
        ,schema : null
        ,definitions : null

        ,__decode_sequence : function(node, elt) {
            var first_node = node.firstChild;
            if (! first_node) {
                return;
            }

            var child;
            var min_occurs = first_node.getAttribute("minOccurs");
            var max_occurs = first_node.getAttribute("maxOccurs");
            if (first_node.nextSibling == null && min_occurs != null
                                               && max_occurs != null) { // it's an array
                elt.is_array = true;
                elt.min_occurs = min_occurs;
                elt.max_occurs = max_occurs;

                child = this.__type_from_node(first_node);

                elt.children = new Object();
                elt.children[child.name] = child;
                elt.children[0] = child;
            }
            else {
                var order=0;
                elt.children = new Object();

                for (var n=first_node; n!=null; n=n.nextSibling) {
                    child = this.__type_from_node(n);

                    elt.children[child.name] = child;
                    elt.children[order] = child;

                    ++order;
                }
            }
        }

        ,__decode_complex_type : function(node, elt) {
            var first_node = node.firstChild;
            if (! first_node) {
                return;
            }

            var child;
            var tn;
            if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                tn = first_node.baseName;
            }
            else {
                tn = first_node.localName;
            }

            if (tn == 'sequence') {
                this.__decode_sequence(first_node, elt);
            }

            this.schema[elt.ns].complex[elt.name] = elt
        }

        ,__decode_simple_type : function(node, elt) {
            this.schema[elt.ns].simple[elt.name] = elt

            for (var n = node.firstChild; n; n=n.nextSibling) {
                var nn;
                if (qx.core.Variant.isSet("qx.client", "mshtml")) {
                    nn = n.baseName;
                }
                else {
                    nn = n.localName;
                }

                if (nn == 'restriction') {
                    elt.base = n.getAttribute("base");
                    elt.base_ns = this.type_qname_to_ns(n,elt.base);
                    elt.restrictions = new Object();
                    for (var r = n.firstChild; r != null; r=r.nextSibling) {
                        // TODO: fill restrictions
                    }
                }
            }
        }

        ,__type_from_node: function(node, ns) {
            var elt = new Object();

            elt.type = node.getAttribute("type");
            elt.name = node.getAttribute("name");
            if (ns) {
                elt.ns = ns;
            }

            if (elt.type) {
                elt.ns = this.type_qname_to_ns(node, elt.type);
            }
            else {
                elt.ns = node.parentNode.getAttribute("targetNamespace")
            }

            elt.base = null;

            return elt;
        }

        ,type_qname_to_ns: function(node, type_qname) {
            var type_defn = type_qname.split(":");
            var retval;

            if (type_defn.length > 0) {
                retval = this.__prefix_map[type_defn[0]];

                if (! retval) {
                    var tnode = node;
                    while (! retval) {
                        retval = tnode.getAttribute("xmlns:" + type_defn[0]);
                        tnode = tnode.parentNode;
                    }

                    if (retval) {
                        this.__prefix_map[type_defn[0]] = retval;
                    }
                }
            }

            return retval;
        }

        ,get_target_namespace: function() {
            return this.__target_namespace;
        }

        ,__get_simple_base : function(child) {
            var retval;
            var type_l = child.type.split(":")[1];
            var simple_type_ns = this.schema[child.ns]

            if (simple_type_ns) {
                var simple_type = simple_type_ns.simple[type_l];

                if (simple_type) {
                    while (simple_type.base != null) {
                        var base_ns = this.schema[simple_type.base_ns]
                        if (base_ns) {
                            var base_l = simple_type.base.split(":")[1];
                            simple_type = base_ns.simple[base_l];

                            qx.core.Assert.assertNotUndefined(simple_type,
                                    "Simple Type " +
                                    "'{" + simple_type.base_ns + "}'" +
                                    " '" + simple_type.base + "' " +
                                    "does not exist");
                        }
                        else {
                            base_ns = null;
                            break;
                        }
                    }

                    if (base_ns) {
                        retval = simple_type.type.split(":")[1];
                    }
                    else {
                        retval = simple_type.base.split(":")[1];
                    }

                    retval = soap.Client.TYPE_MAP[retval];
                }
            }

            return retval;
        }

        ,get_class_map: function(object_namespace, object_name) {
            var ctx=this;
            var retval;

            if (! object_namespace) {
                object_namespace = ctx.__target_namespace;
            }

            if (! object_name) {
                throw new Error("object_name must be defined!");
            }

            qx.log.Logger.debug("creating object: {" + object_namespace + "}"
                                                            + object_name + "");

            var schema = ctx.schema[object_namespace];
            if (! schema) {
                qx.log.Logger.debug("'" + object_namespace + "' not found!");
                return undefined;
            }

            var type = schema.complex[object_name];
            if (! type) {
                qx.log.Logger.debug("'" + object_name + "' not found!");
            }
            else {
                var children = type.children;
                retval = {
                    extend: qx.core.Object,
                    properties: {},
                    statics: {
                        TYPE_DEFINITION: type
                    }
                };

                // get the props
                var props = retval.properties;
                for (var k in children) {
                    var child = children[k];
                    var prop_name = "_" + child.name;
                    if ( (! (prop_name in props))
                                    && children.hasOwnProperty(k)
                                    && isNaN(k) ) {

                        var type_l = child.type.split(":")[1];

                        var prop_type;
                        if (child.is_array) {
                            prop_type = "Array";
                        }
                        else {
                            prop_type = soap.Client.TYPE_MAP[type_l];
                        }

                        if (! prop_type) {
                            prop_type = this.__get_simple_base(child);
                        }

                        if (! prop_type) {
                            prop_type = "Object";
                        }

                        var prop_def = {"check": prop_type, init: null,
                                                                 nullable: true}

                        qx.log.Logger.debug(object_name + "." + prop_name
                                                 + " is a '" + prop_type + "'");

                        props[prop_name] = prop_def;
                    }
                }
            }

            return retval;
        }

        ,get_class: function(object_namespace, object_name) {
            var ctx=this;

            if (! object_name) {
                throw new Error("object_name must be defined!");
            }

            var class_name = object_namespace + "." + object_name;
            var clazz = qx.Class.getByName(class_name);

            if (! clazz) {
                var class_map = this.get_class_map(object_namespace, object_name);
                if (class_map) {
                    clazz = qx.Class.define(class_name, class_map);
                }
            }

            return clazz;
        }

        ,get_object: function(object_namespace, object_name) {
            var clazz = this.get_class(object_namespace, object_name);
            var retval;

            if (clazz) {
                retval = new clazz();
            }

            return retval;
        }

        ,get_table: function(method_name) {
            // methodun dondurdugu veri tipini alır.
            var method_input = this.schema.complex[method_name];
            if (! method_input) {
                throw new Error("Method named '" + method_name +
                                                  "' is not exposed via wsdl.");
            }

            var class_map = {extend: arskom.ui.Table};
        }

        ,get_form: function(object_namespace, object_name) {
            var class_map = this.get_class_map(object_namespace, object_name);
            var props = class_map.properties;
            var form = new qx.ui.form.Form();
            var pd = this.self(arguments).PRIMITIVE_DEFAULTS;

            for (var key in props) {
                if (props.hasOwnProperty(key)) {
                    var name = key.slice(1);
                    var type = props[key].check;

                    if (type in pd) {
                        var wgt = new pd[type]();
                        form.add(wgt, name);
                    }
                }
            }

            return form;
        }

        ,get_form_widget: function(object_namespace, object_name) {
            var form = this.get_form(object_namespace, object_name);
            var retval = new qx.ui.form.renderer.Single(form);
            return retval;
        }
    }
});
<|endoftext|>


<commit_before>import 'regenerator-runtime/runtime'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom'
import Chat from '../Chat'
import Header from './Header'
import { connect } from 'react-redux'
import {
  initChatAsync,
  resetChat,
  turnChatOff
} from 'redux/actions/ChatActions'
import { changePageVisibility } from 'redux/actions/ViewActions'
import {
  initSessionAsync,
  openSigninModal,
  closeSigninModal
} from 'redux/actions/UserActions'
import { addEvent, removeEvent } from 'helpers/listenerHelpers'
import Home from 'containers/Home'
import ContentPage from 'containers/ContentPage'
import Videos from 'containers/Videos'
import Links from 'containers/Links'
import TwinkleXP from 'containers/TwinkleXP'
import Redirect from 'containers/Redirect'
import { recordUserAction } from 'helpers/userDataHelpers'
import {
  fetchNotifications,
  clearNotifications
} from 'redux/actions/NotiActions'
import { siteContent } from './Styles'
import MobileMenu from './MobileMenu'
import { Color, mobileMaxWidth } from 'constants/css'
import { css } from 'emotion'
import Button from 'components/Button'
import SigninModal from 'containers/Signin'
import SearchBox from './SearchBox'

let visibilityChange
let hidden

class App extends Component {
  static propTypes = {
    chatMode: PropTypes.bool,
    initSession: PropTypes.func,
    turnChatOff: PropTypes.func,
    chatNumUnreads: PropTypes.number,
    numNewPosts: PropTypes.number,
    closeSigninModal: PropTypes.func,
    clearNotifications: PropTypes.func,
    fetchNotifications: PropTypes.func,
    resetChat: PropTypes.func,
    loggedIn: PropTypes.bool,
    location: PropTypes.object,
    initChat: PropTypes.func,
    changePageVisibility: PropTypes.func,
    history: PropTypes.object,
    signinModalShown: PropTypes.bool,
    username: PropTypes.string
  }

  state = {
    chatLoading: false,
    scrollPosition: 0,
    updateNoticeShown: false,
    mobileMenuShown: false,
    navScrollPositions: {}
  }

  componentDidMount() {
    const { initSession, location } = this.props
    if (typeof document.hidden !== 'undefined') {
      hidden = 'hidden'
      visibilityChange = 'visibilitychange'
    } else if (typeof document.msHidden !== 'undefined') {
      hidden = 'msHidden'
      visibilityChange = 'msvisibilitychange'
    } else if (typeof document.webkitHidden !== 'undefined') {
      hidden = 'webkitHidden'
      visibilityChange = 'webkitvisibilitychange'
    }
    initSession(location.pathname)
    addEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
    addEvent(document, visibilityChange, this.handleVisibilityChange)
  }

  componentDidUpdate(prevProps) {
    const {
      chatNumUnreads,
      numNewPosts,
      history,
      location,
      loggedIn,
      fetchNotifications,
      clearNotifications
    } = this.props

    const { navScrollPositions } = this.state
    const newNotiNum = numNewPosts + chatNumUnreads

    if (prevProps.loggedIn !== loggedIn) {
      if (loggedIn) {
        fetchNotifications()
      } else {
        clearNotifications()
      }
    }

    if (location !== prevProps.location) {
      if (history.action === 'PUSH') {
        if (loggedIn) {
          recordUserAction({ action: 'navigation', target: location.pathname })
        }
        document.getElementById('react-view').scrollTop = 0
        const navScrollPosition = { [location.key]: 0 }
        this.setState(state => ({
          navScrollPositions: {
            ...state.navScrollPositions,
            ...navScrollPosition
          }
        }))
      } else {
        document.getElementById('react-view').scrollTop =
          navScrollPositions[location.key]
      }
    }

    if (
      this.props.numNewPosts !== prevProps.numNewPosts ||
      this.props.chatNumUnreads !== prevProps.chatNumUnreads
    ) {
      let title = `${newNotiNum > 0 ? '(' + newNotiNum + ') ' : ''}Twinkle`
      document.title = title
    }

    if (this.props.chatMode !== prevProps.chatMode) {
      let title = `${newNotiNum > 0 ? '(' + newNotiNum + ') ' : ''}Twinkle`
      document.title = title
    }
  }

  componentWillUnmount() {
    removeEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
  }

  render() {
    const {
      chatMode,
      closeSigninModal,
      location,
      history,
      signinModalShown,
      turnChatOff,
      username,
      resetChat
    } = this.props
    const {
      chatLoading,
      mobileMenuShown,
      scrollPosition,
      updateNoticeShown
    } = this.state
    return (

        {signinModalShown && <SigninModal show onHide={closeSigninModal} />}
        {mobileMenuShown && (
          <MobileMenu
            chatMode={chatMode}
            location={location}
            history={history}
            username={username}
            onClose={() => this.setState({ mobileMenuShown: false })}
          />
        )}
        {updateNoticeShown && (
          <div
            className={css`
              position: fixed;
              width: 80%;
              left: 10%;
              top: 2rem;
              z-index: 2000;
              background: ${Color.blue()};
              color: #fff;
              padding: 1rem;
              text-align: center;
              font-size: 2rem;
              display: flex;
              flex-direction: column;
              justify-content: center;
              @media (max-width: ${mobileMaxWidth}) {
                width: 100%;
                left: 0;
              }
            `}
          >

              The website has been updated. Click the button below to apply the
              update.

              {
                "Warning: Update is mandatory. Some features will not work properly if you don't update!"
              }

            <Button
              gold
              filled
              style={{ marginTop: '3rem', width: '20%', alignSelf: 'center' }}
              onClick={() => window.location.reload()}
            >
              Update!
            </Button>

        )}

            this.setState({ updateNoticeShown: !match })
          }
          onMobileMenuOpen={() => this.setState({ mobileMenuShown: true })}
        />
        <div className={`${siteContent} ${chatMode && 'hidden'}`}>
          <SearchBox
            className="mobile"
            style={{
              zIndex: 1000,
              padding: '1rem 0'
            }}
          />
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/questions" component={ContentPage} />
            <Route path="/comments" component={ContentPage} />
            <Route path="/discussions" component={ContentPage} />
            <Route path="/videos" component={Videos} />
            <Route path="/links" component={Links} />
            <Route path="/users" component={Home} />
            <Route path="/twinklexp" component={TwinkleXP} />
            <Route path="/users/:username" component={Home} />
            <Route path="/:username" component={Redirect} />
          </Switch>

        {chatMode &&
          this.props.loggedIn && (
            <Chat
              onUnmount={() =>
                resetChat().then(() => {
                  document.getElementById(
                    'react-view'
                  ).scrollTop = scrollPosition
                  turnChatOff()
                })
              }
            />
          )}

    )
  }

  handleVisibilityChange = () => {
    const { changePageVisibility } = this.props
    changePageVisibility(!document[hidden])
  }

  onChatButtonClick = () => {
    const { initChat, chatMode, turnChatOff } = this.props
    this.setState({ chatLoading: true })
    return (chatMode ? turnChatOff() : initChat()).then(() =>
      this.setState({ chatLoading: false })
    )
  }

  onScroll = event => {
    const { chatMode, location } = this.props
    if (!chatMode) {
      this.setState(state => ({
        scrollPosition: document.getElementById('react-view').scrollTop,
        navScrollPositions: {
          ...state.navScrollPositions,
          [location.key]: document.getElementById('react-view').scrollTop
        }
      }))
    }
  }
}

export default connect(
  state => ({
    loggedIn: state.UserReducer.loggedIn,
    numNewPosts: state.NotiReducer.numNewPosts,
    chatMode: state.ChatReducer.chatMode,
    chatNumUnreads: state.ChatReducer.numUnreads,
    signinModalShown: state.UserReducer.signinModalShown,
    username: state.UserReducer.username
  }),
  {
    closeSigninModal,
    openSigninModal,
    initSession: initSessionAsync,
    turnChatOff,
    fetchNotifications,
    clearNotifications,
    initChat: initChatAsync,
    resetChat,
    changePageVisibility
  }
)(App)
<commit_msg>reflect new notification number on tab<commit_after>import 'regenerator-runtime/runtime'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom'
import Chat from '../Chat'
import Header from './Header'
import { connect } from 'react-redux'
import {
  initChatAsync,
  resetChat,
  turnChatOff
} from 'redux/actions/ChatActions'
import { changePageVisibility } from 'redux/actions/ViewActions'
import {
  initSessionAsync,
  openSigninModal,
  closeSigninModal
} from 'redux/actions/UserActions'
import { addEvent, removeEvent } from 'helpers/listenerHelpers'
import Home from 'containers/Home'
import ContentPage from 'containers/ContentPage'
import Videos from 'containers/Videos'
import Links from 'containers/Links'
import TwinkleXP from 'containers/TwinkleXP'
import Redirect from 'containers/Redirect'
import { recordUserAction } from 'helpers/userDataHelpers'
import {
  fetchNotifications,
  clearNotifications
} from 'redux/actions/NotiActions'
import { siteContent } from './Styles'
import MobileMenu from './MobileMenu'
import { Color, mobileMaxWidth } from 'constants/css'
import { css } from 'emotion'
import Button from 'components/Button'
import SigninModal from 'containers/Signin'
import SearchBox from './SearchBox'

let visibilityChange
let hidden

class App extends Component {
  static propTypes = {
    chatMode: PropTypes.bool,
    initSession: PropTypes.func,
    turnChatOff: PropTypes.func,
    chatNumUnreads: PropTypes.number,
    numNewNotis: PropTypes.number,
    numNewPosts: PropTypes.number,
    closeSigninModal: PropTypes.func,
    clearNotifications: PropTypes.func,
    fetchNotifications: PropTypes.func,
    resetChat: PropTypes.func,
    loggedIn: PropTypes.bool,
    location: PropTypes.object,
    initChat: PropTypes.func,
    changePageVisibility: PropTypes.func,
    history: PropTypes.object,
    signinModalShown: PropTypes.bool,
    username: PropTypes.string
  }

  state = {
    chatLoading: false,
    scrollPosition: 0,
    updateNoticeShown: false,
    mobileMenuShown: false,
    navScrollPositions: {}
  }

  componentDidMount() {
    const { initSession, location } = this.props
    if (typeof document.hidden !== 'undefined') {
      hidden = 'hidden'
      visibilityChange = 'visibilitychange'
    } else if (typeof document.msHidden !== 'undefined') {
      hidden = 'msHidden'
      visibilityChange = 'msvisibilitychange'
    } else if (typeof document.webkitHidden !== 'undefined') {
      hidden = 'webkitHidden'
      visibilityChange = 'webkitvisibilitychange'
    }
    initSession(location.pathname)
    addEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
    addEvent(document, visibilityChange, this.handleVisibilityChange)
  }

  componentDidUpdate(prevProps) {
    const {
      chatNumUnreads,
      numNewNotis,
      numNewPosts,
      history,
      location,
      loggedIn,
      fetchNotifications,
      clearNotifications
    } = this.props

    const { navScrollPositions } = this.state
    const newNotiNum = numNewPosts + numNewNotis + chatNumUnreads

    if (prevProps.loggedIn !== loggedIn) {
      if (loggedIn) {
        fetchNotifications()
      } else {
        clearNotifications()
      }
    }

    if (location !== prevProps.location) {
      if (history.action === 'PUSH') {
        if (loggedIn) {
          recordUserAction({ action: 'navigation', target: location.pathname })
        }
        document.getElementById('react-view').scrollTop = 0
        const navScrollPosition = { [location.key]: 0 }
        this.setState(state => ({
          navScrollPositions: {
            ...state.navScrollPositions,
            ...navScrollPosition
          }
        }))
      } else {
        document.getElementById('react-view').scrollTop =
          navScrollPositions[location.key]
      }
    }

    if (
      this.props.numNewPosts !== prevProps.numNewPosts ||
      this.props.chatNumUnreads !== prevProps.chatNumUnreads ||
      this.props.numNewNotis !== prevProps.numNewNotis
    ) {
      let title = `${newNotiNum > 0 ? '(' + newNotiNum + ') ' : ''}Twinkle`
      document.title = title
    }

    if (this.props.chatMode !== prevProps.chatMode) {
      let title = `${newNotiNum > 0 ? '(' + newNotiNum + ') ' : ''}Twinkle`
      document.title = title
    }
  }

  componentWillUnmount() {
    removeEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
  }

  render() {
    const {
      chatMode,
      closeSigninModal,
      location,
      history,
      signinModalShown,
      turnChatOff,
      username,
      resetChat
    } = this.props
    const {
      chatLoading,
      mobileMenuShown,
      scrollPosition,
      updateNoticeShown
    } = this.state
    return (

        {signinModalShown && <SigninModal show onHide={closeSigninModal} />}
        {mobileMenuShown && (
          <MobileMenu
            chatMode={chatMode}
            location={location}
            history={history}
            username={username}
            onClose={() => this.setState({ mobileMenuShown: false })}
          />
        )}
        {updateNoticeShown && (
          <div
            className={css`
              position: fixed;
              width: 80%;
              left: 10%;
              top: 2rem;
              z-index: 2000;
              background: ${Color.blue()};
              color: #fff;
              padding: 1rem;
              text-align: center;
              font-size: 2rem;
              display: flex;
              flex-direction: column;
              justify-content: center;
              @media (max-width: ${mobileMaxWidth}) {
                width: 100%;
                left: 0;
              }
            `}
          >

              The website has been updated. Click the button below to apply the
              update.

              {
                "Warning: Update is mandatory. Some features will not work properly if you don't update!"
              }

            <Button
              gold
              filled
              style={{ marginTop: '3rem', width: '20%', alignSelf: 'center' }}
              onClick={() => window.location.reload()}
            >
              Update!
            </Button>

        )}

            this.setState({ updateNoticeShown: !match })
          }
          onMobileMenuOpen={() => this.setState({ mobileMenuShown: true })}
        />
        <div className={`${siteContent} ${chatMode && 'hidden'}`}>
          <SearchBox
            className="mobile"
            style={{
              zIndex: 1000,
              padding: '1rem 0'
            }}
          />
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/questions" component={ContentPage} />
            <Route path="/comments" component={ContentPage} />
            <Route path="/discussions" component={ContentPage} />
            <Route path="/videos" component={Videos} />
            <Route path="/links" component={Links} />
            <Route path="/users" component={Home} />
            <Route path="/twinklexp" component={TwinkleXP} />
            <Route path="/users/:username" component={Home} />
            <Route path="/:username" component={Redirect} />
          </Switch>

        {chatMode &&
          this.props.loggedIn && (
            <Chat
              onUnmount={() =>
                resetChat().then(() => {
                  document.getElementById(
                    'react-view'
                  ).scrollTop = scrollPosition
                  turnChatOff()
                })
              }
            />
          )}

    )
  }

  handleVisibilityChange = () => {
    const { changePageVisibility } = this.props
    changePageVisibility(!document[hidden])
  }

  onChatButtonClick = () => {
    const { initChat, chatMode, turnChatOff } = this.props
    this.setState({ chatLoading: true })
    return (chatMode ? turnChatOff() : initChat()).then(() =>
      this.setState({ chatLoading: false })
    )
  }

  onScroll = event => {
    const { chatMode, location } = this.props
    if (!chatMode) {
      this.setState(state => ({
        scrollPosition: document.getElementById('react-view').scrollTop,
        navScrollPositions: {
          ...state.navScrollPositions,
          [location.key]: document.getElementById('react-view').scrollTop
        }
      }))
    }
  }
}

export default connect(
  state => ({
    loggedIn: state.UserReducer.loggedIn,
    numNewPosts: state.NotiReducer.numNewPosts,
    numNewNotis: state.NotiReducer.numNewNotis,
    chatMode: state.ChatReducer.chatMode,
    chatNumUnreads: state.ChatReducer.numUnreads,
    signinModalShown: state.UserReducer.signinModalShown,
    username: state.UserReducer.username
  }),
  {
    closeSigninModal,
    openSigninModal,
    initSession: initSessionAsync,
    turnChatOff,
    fetchNotifications,
    clearNotifications,
    initChat: initChatAsync,
    resetChat,
    changePageVisibility
  }
)(App)
<|endoftext|>


<commit_before>import 'regenerator-runtime/runtime'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom'
import Chat from '../Chat'
import Header from './Header'
import { connect } from 'react-redux'
import {
  initChatAsync,
  resetChat,
  turnChatOff
} from 'redux/actions/ChatActions'
import { changePageVisibility } from 'redux/actions/ViewActions'
import { initSessionAsync } from 'redux/actions/UserActions'
import { addEvent, removeEvent } from 'helpers/listenerHelpers'
import Home from 'containers/Home'
import ContentPage from 'containers/ContentPage'
import Videos from 'containers/Videos'
import Links from 'containers/Links'
import TwinkleXP from 'containers/TwinkleXP'
import Redirect from 'containers/Redirect'
import Button from 'components/Button'
import { recordUserAction } from 'helpers/userDataHelpers'
import {
  fetchNotifications,
  clearNotifications
} from 'redux/actions/NotiActions'

let visibilityChange
let hidden

class App extends Component {
  static propTypes = {
    chatMode: PropTypes.bool,
    initSession: PropTypes.func,
    turnChatOff: PropTypes.func,
    chatNumUnreads: PropTypes.number,
    clearNotifications: PropTypes.func,
    fetchNotifications: PropTypes.func,
    resetChat: PropTypes.func,
    loggedIn: PropTypes.bool,
    location: PropTypes.object,
    initChat: PropTypes.func,
    changePageVisibility: PropTypes.func,
    history: PropTypes.object
  }

  state = {
    chatLoading: false,
    scrollPosition: 0,
    updateNoticeShown: false,
    navScrollPositions: {}
  }

  componentDidMount() {
    const { initSession, location } = this.props
    if (typeof document.hidden !== 'undefined') {
      hidden = 'hidden'
      visibilityChange = 'visibilitychange'
    } else if (typeof document.msHidden !== 'undefined') {
      hidden = 'msHidden'
      visibilityChange = 'msvisibilitychange'
    } else if (typeof document.webkitHidden !== 'undefined') {
      hidden = 'webkitHidden'
      visibilityChange = 'webkitvisibilitychange'
    }
    initSession(location.pathname)
    addEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
    addEvent(document, visibilityChange, this.handleVisibilityChange)
  }

  componentDidUpdate(prevProps) {
    let elements = document.documentElement.childNodes
    const {
      chatMode,
      chatNumUnreads,
      history,
      location,
      loggedIn,
      fetchNotifications,
      clearNotifications
    } = this.props

    const { navScrollPositions } = this.state

    if (prevProps.loggedIn !== loggedIn) {
      if (loggedIn) {
        fetchNotifications()
      } else {
        clearNotifications()
      }
    }

    if (location !== prevProps.location) {
      if (history.action === 'PUSH') {
        if (loggedIn) {
          recordUserAction({ action: 'navigation', target: location.pathname })
        }
        document.getElementById('react-view').scrollTop = 0
        const navScrollPosition = { [location.key]: 0 }
        this.setState(state => ({
          navScrollPositions: {
            ...state.navScrollPositions,
            ...navScrollPosition
          }
        }))
      } else {
        document.getElementById('react-view').scrollTop = navScrollPositions[location.key]
      }
    }

    if (this.props.chatNumUnreads !== prevProps.chatNumUnreads) {
      let title = `${
        chatNumUnreads > 0 ? '(' + chatNumUnreads + ') ' : ''
      }Twinkle`
      let display = chatMode ? 'none' : 'inline'
      document.title = title
      for (let i = 0; i < elements.length; i++) {
        if (elements[i].tagName === 'GRAMMARLY-CARD') {
          elements[i].style.display = display
        }
      }
    }

    if (this.props.chatMode !== prevProps.chatMode) {
      let title = `${
        chatNumUnreads > 0 ? '(' + chatNumUnreads + ') ' : ''
      }Twinkle`
      let display = chatMode ? 'none' : 'inline'
      document.title = title
      for (let i = 0; i < elements.length; i++) {
        if (elements[i].tagName === 'GRAMMARLY-CARD') {
          elements[i].style.display = display
        }
      }
    }
  }

  componentWillUnmount() {
    removeEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
  }

  render() {
    const { chatMode, turnChatOff, resetChat, loggedIn } = this.props
    const { chatLoading, scrollPosition, updateNoticeShown } = this.state
    const style =
      chatMode && loggedIn
        ? {
            display: 'none'
          }
        : { paddingTop: '65px' }

    return (

            this.setState({ updateNoticeShown: !match })
          }
        />

          {updateNoticeShown && (

                The website has been updated. Click the button below to apply
                the update.

                {
                  "Warning: Update is mandatory. Some features will not work properly if you don't!"
                }

              <Button
                className="btn btn-lg btn-success"
                style={{
                  marginTop: '1em',
                  fontSize: '1.5em'
                }}
                onClick={() => window.location.reload()}
              >
                Update!
              </Button>

          )}
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/questions" component={ContentPage} />
            <Route path="/comments" component={ContentPage} />
            <Route path="/discussions" component={ContentPage} />
            <Route path="/videos" component={Videos} />
            <Route path="/links" component={Links} />
            <Route path="/users" component={Home} />
            <Route path="/twinklexp" component={TwinkleXP} />
            <Route path="/users/:username" component={Home} />
            <Route path="/:username" component={Redirect} />
          </Switch>

        {chatMode &&
          this.props.loggedIn && (
            <Chat
              onUnmount={() =>
                resetChat().then(() => {
                  document.getElementById('react-view').scrollTop = scrollPosition
                  turnChatOff()
                })
              }
            />
          )}

    )
  }

  handleVisibilityChange = () => {
    const { changePageVisibility } = this.props
    changePageVisibility(!document[hidden])
  }

  onChatButtonClick = () => {
    const { initChat, chatMode, turnChatOff } = this.props
    this.setState({ chatLoading: true })
    return (chatMode ? turnChatOff() : initChat()).then(() =>
      this.setState({ chatLoading: false })
    )
  }

  onScroll = event => {
    const { chatMode, location } = this.props
    if (!chatMode) {
      this.setState(state => ({
        scrollPosition: document.getElementById('react-view').scrollTop,
        navScrollPositions: {
          ...state.navScrollPositions,
          [location.key]: document.getElementById('react-view').scrollTop
        }
      }))
    }
  }
}

export default connect(
  state => ({
    loggedIn: state.UserReducer.loggedIn,
    chatMode: state.ChatReducer.chatMode,
    chatNumUnreads: state.ChatReducer.numUnreads
  }),
  {
    initSession: initSessionAsync,
    turnChatOff,
    fetchNotifications,
    clearNotifications,
    initChat: initChatAsync,
    resetChat,
    changePageVisibility
  }
)(App)
<commit_msg>update notice layout update<commit_after>import 'regenerator-runtime/runtime'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom'
import Chat from '../Chat'
import Header from './Header'
import { connect } from 'react-redux'
import {
  initChatAsync,
  resetChat,
  turnChatOff
} from 'redux/actions/ChatActions'
import { changePageVisibility } from 'redux/actions/ViewActions'
import { initSessionAsync } from 'redux/actions/UserActions'
import { addEvent, removeEvent } from 'helpers/listenerHelpers'
import Home from 'containers/Home'
import ContentPage from 'containers/ContentPage'
import Videos from 'containers/Videos'
import Links from 'containers/Links'
import TwinkleXP from 'containers/TwinkleXP'
import Redirect from 'containers/Redirect'
import Button from 'components/Button'
import { recordUserAction } from 'helpers/userDataHelpers'
import {
  fetchNotifications,
  clearNotifications
} from 'redux/actions/NotiActions'

let visibilityChange
let hidden

class App extends Component {
  static propTypes = {
    chatMode: PropTypes.bool,
    initSession: PropTypes.func,
    turnChatOff: PropTypes.func,
    chatNumUnreads: PropTypes.number,
    clearNotifications: PropTypes.func,
    fetchNotifications: PropTypes.func,
    resetChat: PropTypes.func,
    loggedIn: PropTypes.bool,
    location: PropTypes.object,
    initChat: PropTypes.func,
    changePageVisibility: PropTypes.func,
    history: PropTypes.object
  }

  state = {
    chatLoading: false,
    scrollPosition: 0,
    updateNoticeShown: false,
    navScrollPositions: {}
  }

  componentDidMount() {
    const { initSession, location } = this.props
    if (typeof document.hidden !== 'undefined') {
      hidden = 'hidden'
      visibilityChange = 'visibilitychange'
    } else if (typeof document.msHidden !== 'undefined') {
      hidden = 'msHidden'
      visibilityChange = 'msvisibilitychange'
    } else if (typeof document.webkitHidden !== 'undefined') {
      hidden = 'webkitHidden'
      visibilityChange = 'webkitvisibilitychange'
    }
    initSession(location.pathname)
    addEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
    addEvent(document, visibilityChange, this.handleVisibilityChange)
  }

  componentDidUpdate(prevProps) {
    let elements = document.documentElement.childNodes
    const {
      chatMode,
      chatNumUnreads,
      history,
      location,
      loggedIn,
      fetchNotifications,
      clearNotifications
    } = this.props

    const { navScrollPositions } = this.state

    if (prevProps.loggedIn !== loggedIn) {
      if (loggedIn) {
        fetchNotifications()
      } else {
        clearNotifications()
      }
    }

    if (location !== prevProps.location) {
      if (history.action === 'PUSH') {
        if (loggedIn) {
          recordUserAction({ action: 'navigation', target: location.pathname })
        }
        document.getElementById('react-view').scrollTop = 0
        const navScrollPosition = { [location.key]: 0 }
        this.setState(state => ({
          navScrollPositions: {
            ...state.navScrollPositions,
            ...navScrollPosition
          }
        }))
      } else {
        document.getElementById('react-view').scrollTop =
          navScrollPositions[location.key]
      }
    }

    if (this.props.chatNumUnreads !== prevProps.chatNumUnreads) {
      let title = `${
        chatNumUnreads > 0 ? '(' + chatNumUnreads + ') ' : ''
      }Twinkle`
      let display = chatMode ? 'none' : 'inline'
      document.title = title
      for (let i = 0; i < elements.length; i++) {
        if (elements[i].tagName === 'GRAMMARLY-CARD') {
          elements[i].style.display = display
        }
      }
    }

    if (this.props.chatMode !== prevProps.chatMode) {
      let title = `${
        chatNumUnreads > 0 ? '(' + chatNumUnreads + ') ' : ''
      }Twinkle`
      let display = chatMode ? 'none' : 'inline'
      document.title = title
      for (let i = 0; i < elements.length; i++) {
        if (elements[i].tagName === 'GRAMMARLY-CARD') {
          elements[i].style.display = display
        }
      }
    }
  }

  componentWillUnmount() {
    removeEvent(document.getElementById('react-view'), 'scroll', this.onScroll)
  }

  render() {
    const { chatMode, turnChatOff, resetChat, loggedIn } = this.props
    const { chatLoading, scrollPosition, updateNoticeShown } = this.state
    const style =
      chatMode && loggedIn
        ? {
            display: 'none'
          }
        : { paddingTop: '65px' }

    return (

        {updateNoticeShown && (

              The website has been updated. Click the button below to apply the
              update.

              {
                "Warning: Update is mandatory. Some features will not work properly if you don't!"
              }

            <Button
              className="btn btn-lg btn-success"
              style={{
                marginTop: '1em',
                fontSize: '1.5em'
              }}
              onClick={() => window.location.reload()}
            >
              Update!
            </Button>

        )}

            this.setState({ updateNoticeShown: !match })
          }
        />

          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/questions" component={ContentPage} />
            <Route path="/comments" component={ContentPage} />
            <Route path="/discussions" component={ContentPage} />
            <Route path="/videos" component={Videos} />
            <Route path="/links" component={Links} />
            <Route path="/users" component={Home} />
            <Route path="/twinklexp" component={TwinkleXP} />
            <Route path="/users/:username" component={Home} />
            <Route path="/:username" component={Redirect} />
          </Switch>

        {chatMode &&
          this.props.loggedIn && (
            <Chat
              onUnmount={() =>
                resetChat().then(() => {
                  document.getElementById(
                    'react-view'
                  ).scrollTop = scrollPosition
                  turnChatOff()
                })
              }
            />
          )}

    )
  }

  handleVisibilityChange = () => {
    const { changePageVisibility } = this.props
    changePageVisibility(!document[hidden])
  }

  onChatButtonClick = () => {
    const { initChat, chatMode, turnChatOff } = this.props
    this.setState({ chatLoading: true })
    return (chatMode ? turnChatOff() : initChat()).then(() =>
      this.setState({ chatLoading: false })
    )
  }

  onScroll = event => {
    const { chatMode, location } = this.props
    if (!chatMode) {
      this.setState(state => ({
        scrollPosition: document.getElementById('react-view').scrollTop,
        navScrollPositions: {
          ...state.navScrollPositions,
          [location.key]: document.getElementById('react-view').scrollTop
        }
      }))
    }
  }
}

export default connect(
  state => ({
    loggedIn: state.UserReducer.loggedIn,
    chatMode: state.ChatReducer.chatMode,
    chatNumUnreads: state.ChatReducer.numUnreads
  }),
  {
    initSession: initSessionAsync,
    turnChatOff,
    fetchNotifications,
    clearNotifications,
    initChat: initChatAsync,
    resetChat,
    changePageVisibility
  }
)(App)
<|endoftext|>


<commit_before>/**
 * Tutorial controller
 * @type {*|exports|module.exports}
 */
var express = require('express');
var Rooms = require('../models/Rooms');
var Tutorial = require('../models/Tutorial');
var lobby = Rooms.getLobby();
var app = require('../../app');

var protocol = 'https';
var usehttps = app.get('use-https');
if (!usehttps) {
	protocol = 'http';
}

/**
 * Default get method
 * @param req
 * @param res
 * @param next
 */
var get = function(req, res, next){
	var userID = req.body.auth.decoded.id;
	var tutorialRoomID = req.params.id;

	if (Rooms.hasUser(tutorialRoomID, userID)) {
		if (Rooms.isActive(tutorialRoomID)) {
			res.render(
				'tutorial',{
					roomId: req.params.id,
					roomioURL: protocol + '://' + req.app.get('server-ip') + ':' + req.app.get('server-port') + '/room',
					title: 'Tutorial UI',
					ip: req.app.get('server-ip')
				});
		} else {
			res.render(
				'error', {
					message:'Room Not Exists',
					error: {
						status: 'Room Not Exists',
						stack: 'controllers/Tutorial.js'
					}
				}
			)
		}
	} else {
		res.render(
			'error', {
				message:'Permission Denied',
				error: {
					status: 'No Permission',
					stack: 'controllers/Tutorial.js'
				}
			}
		)
	}
};

/**
 * create room RESTFUL API in post method
 * @param req
 * @param res
 * @param next
 */
var createRoom = function(req, res, next){
	var userID = req.body.auth.decoded.id;
	var tutorialRoomID = req.body.roomID;
	if (Rooms.hasTutor(tutorialRoomID, userID)) {
		if (!Rooms.isActive(tutorialRoomID)) {
			var room = new Rooms.Room();
			lobby.get(tutorialRoomID).setActive();
			res.json({success:true, at:'room creation', roomID:tutorialRoomID});
		} else {
			res.json({success:false, at:'room creation', message:'Room already exists'});
		}
	} else {
		res.json({success:false, at:'room create', message: 'Permission Denied, you have no permission to create room'});
	}
};

/**
 * get room parameters RESTFUL API in post method
 * @param req
 * @param res
 * @param next
 * @returns {*}
 */
var roomParams = function (req, res, next){
	//not yet implemented!
	var roomId = req.body.roomId;
	if (lobby.getRoomsMap()[roomId]){
		return res.json({success:true, at:'getting room parameters', lobby:lobby});
	} else {
		return res.json({success:false, at:'getting room parameters', message:'Room has not been created yet'});
	}
};

module.exports.get = get;
module.exports.createRoom = createRoom;
module.exports.roomParams = roomParams;<commit_msg>Delete roomparam<commit_after>/**
 * Tutorial controller
 * @type {*|exports|module.exports}
 */
var express = require('express');
var Rooms = require('../models/Rooms');
var Tutorial = require('../models/Tutorial');
var lobby = Rooms.getLobby();
var app = require('../../app');

var protocol = 'https';
var usehttps = app.get('use-https');
if (!usehttps) {
	protocol = 'http';
}

/**
 * Default get method
 * @param req
 * @param res
 * @param next
 */
var get = function(req, res, next){
	var userID = req.body.auth.decoded.id;
	var tutorialRoomID = req.params.id;

	console.log(JSON.stringify(Rooms.getLobby()));
	if (Rooms.hasUser(tutorialRoomID, userID)) {
		if (Rooms.isActive(tutorialRoomID)) {
			res.render(
				'tutorial',{
					roomId: req.params.id,
					roomioURL: protocol + '://' + req.app.get('server-ip') + ':' + req.app.get('server-port') + '/room',
					title: 'Tutorial UI',
					ip: req.app.get('server-ip')
				});
		} else {
			res.render(
				'error', {
					message:'Room Not Exists',
					error: {
						status: 'Room Not Exists',
						stack: 'controllers/Tutorial.js'
					}
				}
			)
		}
	} else {
		res.render(
			'error', {
				message:'Permission Denied',
				error: {
					status: 'No Permission',
					stack: 'controllers/Tutorial.js'
				}
			}
		)
	}
};

/**
 * create room RESTFUL API in post method
 * @param req
 * @param res
 * @param next
 */
var createRoom = function(req, res, next){
	var userID = req.body.auth.decoded.id;
	var tutorialRoomID = req.body.roomID;
	if (Rooms.hasTutor(tutorialRoomID, userID)) {
		if (!Rooms.isActive(tutorialRoomID)) {
			var room = new Rooms.Room();
			lobby.get(tutorialRoomID).setActive();
			res.json({success:true, at:'room creation', roomID:tutorialRoomID});
		} else {
			res.json({success:false, at:'room creation', message:'Room already exists'});
		}
	} else {
		res.json({success:false, at:'room create', message: 'Permission Denied, you have no permission to create room'});
	}
};

module.exports.get = get;
module.exports.createRoom = createRoom;<|endoftext|>