<commit_before>import styled from 'styled-components';
import { FieldGroup } from '../fields';
import { Container as BinaryFieldContainer } from '../fields/BinaryField';
import { Container as FieldWrapperContainer } from '../fields/FieldWrapper';
import { Container as AccordionContainer } from '../Accordion';
import FormColumn from './FormColumn';
import FormText from './FormText';

// TODO: simplify field layout by wrapping all single fields in a single container element,
// so we don't have to select on so many different types of classes here

const Form = styled.form.withConfig({ displayName: 'Form' })`
  background: 'transparent';
  color: inherit;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: stretch;

  /* these are field groups which help layout rows inside a form */
  & ${FieldGroup},
  & ${FormText} {
    flex: 1 0 100%;
    margin-top: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
    margin-bottom: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
  }

  & > ${FormColumn} {
    flex: 1 0 50%;
  }

  /* these are inputs directly within a field group inside a form */
  & ${FieldGroup} > ${FieldWrapperContainer}:not(:first-child),
  & ${FieldGroup} > ${BinaryFieldContainer}:not(:first-child) {
    margin-left: ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px;
  }
  & ${FieldGroup} > ${FieldWrapperContainer}:not(:last-child),
  & ${FieldGroup} > ${BinaryFieldContainer}:not(:last-child) {
    margin-right: ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px;
  }

  /* these are 'loose' inputs placed directly inside a form */
  & > ${FieldWrapperContainer},
  & > ${BinaryFieldContainer},
  & ${AccordionContainer} ${FieldWrapperContainer},
  & ${AccordionContainer} ${BinaryFieldContainer} {
    margin: ${({ theme }) => theme.input.margin};
    margin-top: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
    margin-bottom: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;

    /*
      loose inputs naturally take up about 1/2 width.
      we don't enforce this with margin, since that would cause extra margins on the 'outside'
      of the form. Instead, we specify how much space should be between inputs by subtracting it
      from their flex-basis, and then use the Form's justify-content and wrapping to make sure that
      space goes between the items on the inside of the form.
    */
    flex: 0 1 calc(50% - ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px);
  }

  & > ${FieldGroup}:last-child,
  & > ${FormText}:last-child,
  & > ${FieldWrapperContainer}:last-child,
  & > ${BinaryFieldContainer}:last-child {
    margin-bottom: 0;
  }
  & > ${FieldGroup}:first-child,
  & > ${FormText}:first-child,
  & > ${FieldWrapperContainer}:first-child,
  & > ${BinaryFieldContainer}:first-child {
    margin-top: 0;
  }

  &:invalid button[type="submit"] {
    background: ${({ theme }) => theme.button.disabledBG};
    color: ${({ theme }) => theme.button.disabledFG};
    border: ${({ theme }) => theme.button.disabledBorder};
    cursor: default;
    box-shadow: none;
  }
  &:invalid button[type="submit"]::after {
    left: 160%;
  }
  &:invalid button[type="submit"]::before {
    left: -60%;
  }
`;

Form.usage = `
# Form

Form is a smart layout component. It tries its best to lay out any Input components you place within it in a reasonable way. There are two ways to put Inputs in forms:

1. 'Loose' inputs, placed directly in the form. The form will attempt to size these inputs to half the total width of the form.

2. FieldGroups, which take up a full row in the form, and can align / size their child inputs however they want using FlexBox.

Regardless of whether Inputs are 'loose' or inside a FieldGroup, the Form will try to put the proper padding between them and ensure that the outside edges are not padded.

\`\`\`
<FormBox>
  <Form>
    <TextInput />
    <TextInput />
    <FieldGroup>
      <ButtonInput />
      <LinkInput />
    </FieldGroup>
  </Form>
</FormBox>
\`\`\`
`;

export default Form;
<commit_msg>accordian-rule add a new style rule in form for accordian<commit_after>import styled from 'styled-components';
import { FieldGroup } from '../fields';
import { Container as BinaryFieldContainer } from '../fields/BinaryField';
import { Container as FieldWrapperContainer } from '../fields/FieldWrapper';
import { Container as AccordionContainer } from '../Accordion';
import FormColumn from './FormColumn';
import FormText from './FormText';

// TODO: simplify field layout by wrapping all single fields in a single container element,
// so we don't have to select on so many different types of classes here

const Form = styled.form.withConfig({ displayName: 'Form' })`
  background: 'transparent';
  color: inherit;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: stretch;

  /* these are field groups which help layout rows inside a form */
  & ${FieldGroup},
  & ${FormText} {
    flex: 1 0 100%;
    margin-top: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
    margin-bottom: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
  }

  & > ${FormColumn} {
    flex: 1 0 50%;
  }

  & > ${AccordionContainer} {
    flex: 1 0 100%;
  }

  /* these are inputs directly within a field group inside a form */
  & ${FieldGroup} > ${FieldWrapperContainer}:not(:first-child),
  & ${FieldGroup} > ${BinaryFieldContainer}:not(:first-child) {
    margin-left: ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px;
  }
  & ${FieldGroup} > ${FieldWrapperContainer}:not(:last-child),
  & ${FieldGroup} > ${BinaryFieldContainer}:not(:last-child) {
    margin-right: ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px;
  }

  /* these are 'loose' inputs placed directly inside a form */
  & > ${FieldWrapperContainer},
  & > ${BinaryFieldContainer},
  & ${AccordionContainer} ${FieldWrapperContainer},
  & ${AccordionContainer} ${BinaryFieldContainer} {
    margin: ${({ theme }) => theme.input.margin};
    margin-top: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;
    margin-bottom: ${({ theme }) => theme.form.elementVerticalSpacing / 2}px;

    /*
      loose inputs naturally take up about 1/2 width.
      we don't enforce this with margin, since that would cause extra margins on the 'outside'
      of the form. Instead, we specify how much space should be between inputs by subtracting it
      from their flex-basis, and then use the Form's justify-content and wrapping to make sure that
      space goes between the items on the inside of the form.
    */
    flex: 0 1 calc(50% - ${({ theme }) => theme.form.elementHorizontalSpacing / 2}px);
  }

  & > ${FieldGroup}:last-child,
  & > ${FormText}:last-child,
  & > ${FieldWrapperContainer}:last-child,
  & > ${BinaryFieldContainer}:last-child {
    margin-bottom: 0;
  }
  & > ${FieldGroup}:first-child,
  & > ${FormText}:first-child,
  & > ${FieldWrapperContainer}:first-child,
  & > ${BinaryFieldContainer}:first-child {
    margin-top: 0;
  }

  &:invalid button[type="submit"] {
    background: ${({ theme }) => theme.button.disabledBG};
    color: ${({ theme }) => theme.button.disabledFG};
    border: ${({ theme }) => theme.button.disabledBorder};
    cursor: default;
    box-shadow: none;
  }
  &:invalid button[type="submit"]::after {
    left: 160%;
  }
  &:invalid button[type="submit"]::before {
    left: -60%;
  }
`;

Form.usage = `
# Form

Form is a smart layout component. It tries its best to lay out any Input components you place within it in a reasonable way. There are two ways to put Inputs in forms:

1. 'Loose' inputs, placed directly in the form. The form will attempt to size these inputs to half the total width of the form.

2. FieldGroups, which take up a full row in the form, and can align / size their child inputs however they want using FlexBox.

Regardless of whether Inputs are 'loose' or inside a FieldGroup, the Form will try to put the proper padding between them and ensure that the outside edges are not padded.

\`\`\`
<FormBox>
  <Form>
    <TextInput />
    <TextInput />
    <FieldGroup>
      <ButtonInput />
      <LinkInput />
    </FieldGroup>
  </Form>
</FormBox>
\`\`\`
`;

export default Form;
<|endoftext|>


<commit_before>// This function takes the raw result of a shelljs command and figures out how to print it.
// Invoke this *REGARDLESS* of what the command returns, it will figure it out.
function printCmdRet(ret) {
  // This is way to complicated. It should get much easier once shelljs/shelljs#356 is fixed.
  if (ret) {
    if (typeof ret.stdout !== 'undefined' && typeof ret.stderr !== 'undefined') {
      if (ret.stdout) console.log(ret.stdout);
      if (ret.stderr) console.error(ret.stderr);
    } else if (ret.output) {
      console.log(ret.output);
    } else if (Array.isArray(ret)) {
      console.log(ret.join('\n'));
    } else {
      console.log(ret);
    }
  }
}

module.exports = printCmdRet;
<commit_msg>refactor(printCmdRet): update to es6<commit_after>// This function takes the raw result of a shelljs command and figures out how to print it.
// Invoke this *REGARDLESS* of what the command returns, it will figure it out.
const printCmdRet = (ret) => {
  if (!ret) return;

  // This is way to complicated. It should get much easier once shelljs/shelljs#356 is fixed.
  if (ret.stdout && ret.stderr) {
    if (ret.stdout) console.log(ret.stdout);
    if (ret.stderr) console.error(ret.stderr);
  } else if (ret.output) {
    console.log(ret.output);
  } else if (Array.isArray(ret)) {
    console.log(ret.join('\n'));
  } else {
    console.log(ret);
  }
};

export default printCmdRet;
<|endoftext|>


<commit_before>import request from 'superagent-bluebird-promise';
import { browserHistory } from 'react-router';

import { ACTION_TYPES } from './ActionTypes.js';
import { buildUrl, catchHandler } from './fetch.js';
import { addNotification as notify } from 'reapop';
import t from '../trans.js';

// https://github.com/LouisBarranqueiro/reapop/blob/master/docs/api.md#customize-default-values-for-notifications
export const notifySettings = {
  status: 'success',
  position: 'br',
  dismissible: true,
  dismissAfter: 2000,
  closeButton: false,
  allowHTML: false,
};
export function success(msg) {
  return notify({
    status: 'success',
    title: t('toastrSuccessTitle'),
    message: msg
  });
}
export function failure() {
  return notify({
    status: 'error',
    position: 'tc',
    dismissAfter: 4000,
    title: t('toastrFailureTitle'),
    message: t('toastrFailure'),
  });
}

export function busyToggle() {
  return {type: ACTION_TYPES.APP_BUSYTOGGLE, why: 'moreBusy'};
}
busyToggle.off = function() {
  return {type: ACTION_TYPES.APP_BUSYTOGGLE, why: 'lessBusy'};
};

export function updateConfig(newConfig) {
  return dispatch => {
    dispatch(busyToggle());
    return request.post(buildUrl('/config'))
      .set('Content-Type', 'application/json')
      .send(newConfig)
      .then(() => {
        dispatch({type: ACTION_TYPES.CONFIG_UPDATE, config: newConfig});
        dispatch(success(t('config.popupMessage')));
      })
      .catch(catchHandler)
      .then(() => dispatch(busyToggle.off()));
  };
}

export function updateInvoiceFilters(filters) {
  return {
    type: ACTION_TYPES.APP_INVOICE_FILTERSUPDATED,
    filters
  };
}

export function saveClient(client) {
  // console.log('saveingClient', client);
  return dispatch => {
    dispatch(busyToggle());
    return request.post(buildUrl('/clients'))
      .set('Content-Type', 'application/json')
      .send(client)
      .then(res => {
        // console.log('savedClient return', res.body);
        dispatch({
          type: ACTION_TYPES.CLIENT_UPDATE,
          client: res.body,
          isNewClient: !client._id
        });
        dispatch(success(t('config.popupMessage')));
        if (res.body.active === client.active) {
          browserHistory.push('/clients');
        }
      })
      .catch(catchHandler)
      .then(() => dispatch(busyToggle.off()));
  };
}<commit_msg>after saving client, do history.back()<commit_after>import request from 'superagent-bluebird-promise';

import { ACTION_TYPES } from './ActionTypes.js';
import { buildUrl, catchHandler } from './fetch.js';
import { addNotification as notify } from 'reapop';
import t from '../trans.js';

// https://github.com/LouisBarranqueiro/reapop/blob/master/docs/api.md#customize-default-values-for-notifications
export const notifySettings = {
  status: 'success',
  position: 'br',
  dismissible: true,
  dismissAfter: 2000,
  closeButton: false,
  allowHTML: false,
};
export function success(msg) {
  return notify({
    status: 'success',
    title: t('toastrSuccessTitle'),
    message: msg
  });
}
export function failure() {
  return notify({
    status: 'error',
    position: 'tc',
    dismissAfter: 4000,
    title: t('toastrFailureTitle'),
    message: t('toastrFailure'),
  });
}

export function busyToggle() {
  return {type: ACTION_TYPES.APP_BUSYTOGGLE, why: 'moreBusy'};
}
busyToggle.off = function() {
  return {type: ACTION_TYPES.APP_BUSYTOGGLE, why: 'lessBusy'};
};

export function updateConfig(newConfig) {
  return dispatch => {
    dispatch(busyToggle());
    return request.post(buildUrl('/config'))
      .set('Content-Type', 'application/json')
      .send(newConfig)
      .then(() => {
        dispatch({type: ACTION_TYPES.CONFIG_UPDATE, config: newConfig});
        dispatch(success(t('config.popupMessage')));
      })
      .catch(catchHandler)
      .then(() => dispatch(busyToggle.off()));
  };
}

export function updateInvoiceFilters(filters) {
  return {
    type: ACTION_TYPES.APP_INVOICE_FILTERSUPDATED,
    filters
  };
}

export function saveClient(client) {
  // console.log('saveingClient', client);
  return dispatch => {
    dispatch(busyToggle());
    return request.post(buildUrl('/clients'))
      .set('Content-Type', 'application/json')
      .send(client)
      .then(res => {
        // console.log('savedClient return', res.body);
        dispatch({
          type: ACTION_TYPES.CLIENT_UPDATE,
          client: res.body,
          isNewClient: !client._id
        });
        dispatch(success(t('config.popupMessage')));
        if (res.body.active === client.active) {
          window.history.back();
        }
      })
      .catch(catchHandler)
      .then(() => dispatch(busyToggle.off()));
  };
}<|endoftext|>


<commit_before>/* globals popover isRtl menu */
const setStatus = status => {
	AccountBox.setStatus(status);
	RocketChat.callbacks.run('userStatusManuallySet', status);
	popover.close();
};

const viewModeIcon = {
	extended: 'th-list',
	medium: 'list',
	condensed: 'list-alt'
};

const extendedViewOption = (user) => {
	if (RocketChat.settings.get('Store_Last_Message')) {
		return {
			icon: viewModeIcon.extended,
			name: t('Extended'),
			modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'extended' ? 'bold' : null,
			action: () => {
				Meteor.call('saveUserPreferences', {sidebarViewMode: 'extended'}, function(error) {
					if (error) {
						return handleError(error);
					}
				});
			}
		};
	}

	return;
};

const toolbarButtons = (user) => {
	return [{
		name: t('Search'),
		icon: 'magnifier',
		action: () => {
			const toolbarEl = $('.toolbar');
			toolbarEl.css('display', 'block');
			toolbarEl.find('.rc-input__element').focus();
		}
	},
	{
		name: t('Browse_channels'),
		icon: 'globe'
	},
	{
		name: t('View_mode'),
		icon: () => RocketChat.getUserPreference(user, 'sidebarViewMode') ? viewModeIcon[RocketChat.getUserPreference(user, 'sidebarViewMode')] : viewModeIcon.condensed,
		action: (e) => {
			const hideAvatarSetting = RocketChat.getUserPreference(user, 'sidebarHideAvatar');
			const config = {
				columns: [
					{
						groups: [
							{
								items: [
									extendedViewOption(user),
									{
										icon: viewModeIcon.medium,
										name: t('Medium'),
										modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'medium' ? 'bold' : null,
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarViewMode: 'medium'}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									},
									{
										icon: viewModeIcon.condensed,
										name: t('Condensed'),
										modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'condensed' ? 'bold' : null,
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarViewMode: 'condensed'}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									}
								]
							},
							{
								items: [
									{
										icon: 'user-rounded',
										name: hideAvatarSetting ? t('Show_Avatars') : t('Hide_Avatars'),
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarHideAvatar: !hideAvatarSetting}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									}
								]
							}
						]
					}
				],
				mousePosition: () => ({
					x: e.currentTarget.getBoundingClientRect().left,
					y: e.currentTarget.getBoundingClientRect().bottom + 50
				}),
				customCSSProperties: () => ({
					top:  `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`,
					left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px`
				})
			};

			popover.open(config);
		}
	},
	{
		name: t('Sort'),
		icon: 'sort',
		action: (e) => {

			const options = [];
			const config = {
				template: 'sortlist',
				mousePosition: () => ({
					x: e.currentTarget.getBoundingClientRect().left,
					y: e.currentTarget.getBoundingClientRect().bottom + 50
				}),
				customCSSProperties: () => ({
					top:  `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`,
					left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px`
				}),
				data: {
					// value: instance.form[key].get(),
					options
				}
			};
			popover.open(config);
		}
	},
	{
		name: t('Create_A_New_Channel'),
		icon: 'plus',
		condition: () => RocketChat.authz.hasAtLeastOnePermission(['create-c', 'create-p']),
		action: () => {
			menu.close();
			FlowRouter.go('create-channel');
		}
	},
	{
		name: t('Options'),
		icon: 'menu',
		condition: () => !(Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')),
		action: () => {
			let adminOption;
			if (RocketChat.authz.hasAtLeastOnePermission(['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) || (RocketChat.AdminBox.getOptions().length > 0)) {
				adminOption = {
					icon: 'customize',
					name: t('Administration'),
					type: 'open',
					id: 'administration',
					action: () => {
						SideNav.setFlex('adminFlex');
						SideNav.openFlex();
						FlowRouter.go('admin-info');
						popover.close();
					}
				};
			}

			const sidebarHeader = document.querySelector('.sidebar__header');
			const sidebarHeaderPadding = parseInt(getComputedStyle(sidebarHeader)['padding-left'].replace('px', '')) * 2;
			const sidebarHeaderMargin = parseInt(getComputedStyle(sidebarHeader)['margin-left'].replace('px', '')) * 2;

			const config = {
				popoverClass: 'sidebar-header',
				columns: [
					{
						groups: [
							{
								title: t('User'),
								items: [
									{
										icon: 'circle',
										name: t('Online'),
										modifier: 'online',
										action: () => setStatus('online')
									},
									{
										icon: 'circle',
										name: t('Away'),
										modifier: 'away',
										action: () => setStatus('away')
									},
									{
										icon: 'circle',
										name: t('Busy'),
										modifier: 'busy',
										action: () => setStatus('busy')
									},
									{
										icon: 'circle',
										name: t('Invisible'),
										modifier: 'offline',
										action: () => setStatus('offline')
									}
								]
							},
							{
								items: AccountBox.getItems().map(item => {
									let action;

									if (item.href) {
										action = () => {
											FlowRouter.go(item.href);
											popover.close();
										};
									}

									if (item.sideNav) {
										action = () => {
											SideNav.setFlex(item.sideNav);
											SideNav.openFlex();
											popover.close();
										};
									}

									return {
										icon: item.icon,
										name: t(item.name),
										type: 'open',
										id: item.name,
										href: item.href,
										sideNav: item.sideNav,
										action
									};
								}).concat([
									adminOption,
									{
										icon: 'user',
										name: t('My_Account'),
										type: 'open',
										id: 'account',
										action: () => {
											SideNav.setFlex('accountFlex');
											SideNav.openFlex();
											FlowRouter.go('account');
											popover.close();
										}
									},
									{
										icon: 'sign-out',
										name: t('Logout'),
										type: 'open',
										id: 'logout',
										action: () => {
											// const user = Meteor.user();
											Meteor.logout(() => {
												RocketChat.callbacks.run('afterLogoutCleanUp', user);
												Meteor.call('logoutCleanUp', user);
												FlowRouter.go('home');
												popover.close();
											});
										}
									}
								])
							}
						]
					}
				],
				position: {
					top: sidebarHeader.offsetHeight
				},
				customCSSProperties: {
					width: `${ sidebarHeader.offsetWidth - sidebarHeaderPadding + sidebarHeaderMargin }px`,
					left: isRtl() ? 'auto' : getComputedStyle(sidebarHeader)['padding-left'],
					right: isRtl() ? getComputedStyle(sidebarHeader)['padding-left'] : 'auto'
				}
			};

			popover.open(config);
		}
	}];
};
Template.sidebarHeader.helpers({
	myUserInfo() {
		if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
			return {
				username: 'anonymous',
				status: 'online'
			};
		}

		const user = Meteor.user() || {};
		const { username } = user;
		const userStatus = Session.get(`user_${ username }_status`);

		return {
			username,
			status: userStatus
		};
	},
	toolbarButtons() {
		return toolbarButtons(Meteor.user()).filter(button => !button.condition || button.condition());
	}
});

Template.sidebarHeader.events({
	'click .js-button'(e) {
		return this.action && this.action.apply(this, [e]);
	}
});
<commit_msg>remove tooltip on click sidebarheader<commit_after>/* globals popover isRtl menu */
const setStatus = status => {
	AccountBox.setStatus(status);
	RocketChat.callbacks.run('userStatusManuallySet', status);
	popover.close();
};

const viewModeIcon = {
	extended: 'th-list',
	medium: 'list',
	condensed: 'list-alt'
};

const extendedViewOption = (user) => {
	if (RocketChat.settings.get('Store_Last_Message')) {
		return {
			icon: viewModeIcon.extended,
			name: t('Extended'),
			modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'extended' ? 'bold' : null,
			action: () => {
				Meteor.call('saveUserPreferences', {sidebarViewMode: 'extended'}, function(error) {
					if (error) {
						return handleError(error);
					}
				});
			}
		};
	}

	return;
};

const toolbarButtons = (user) => {
	return [{
		name: t('Search'),
		icon: 'magnifier',
		action: () => {
			const toolbarEl = $('.toolbar');
			toolbarEl.css('display', 'block');
			toolbarEl.find('.rc-input__element').focus();
		}
	},
	{
		name: t('Browse_channels'),
		icon: 'globe'
	},
	{
		name: t('View_mode'),
		icon: () => RocketChat.getUserPreference(user, 'sidebarViewMode') ? viewModeIcon[RocketChat.getUserPreference(user, 'sidebarViewMode')] : viewModeIcon.condensed,
		action: (e) => {
			const hideAvatarSetting = RocketChat.getUserPreference(user, 'sidebarHideAvatar');
			const config = {
				columns: [
					{
						groups: [
							{
								items: [
									extendedViewOption(user),
									{
										icon: viewModeIcon.medium,
										name: t('Medium'),
										modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'medium' ? 'bold' : null,
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarViewMode: 'medium'}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									},
									{
										icon: viewModeIcon.condensed,
										name: t('Condensed'),
										modifier: RocketChat.getUserPreference(user, 'sidebarViewMode') === 'condensed' ? 'bold' : null,
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarViewMode: 'condensed'}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									}
								]
							},
							{
								items: [
									{
										icon: 'user-rounded',
										name: hideAvatarSetting ? t('Show_Avatars') : t('Hide_Avatars'),
										action: () => {
											Meteor.call('saveUserPreferences', {sidebarHideAvatar: !hideAvatarSetting}, function(error) {
												if (error) {
													return handleError(error);
												}
											});
										}
									}
								]
							}
						]
					}
				],
				mousePosition: () => ({
					x: e.currentTarget.getBoundingClientRect().left,
					y: e.currentTarget.getBoundingClientRect().bottom + 50
				}),
				customCSSProperties: () => ({
					top:  `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`,
					left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px`
				})
			};

			popover.open(config);
		}
	},
	{
		name: t('Sort'),
		icon: 'sort',
		action: (e) => {

			const options = [];
			const config = {
				template: 'sortlist',
				mousePosition: () => ({
					x: e.currentTarget.getBoundingClientRect().left,
					y: e.currentTarget.getBoundingClientRect().bottom + 50
				}),
				customCSSProperties: () => ({
					top:  `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`,
					left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px`
				}),
				data: {
					// value: instance.form[key].get(),
					options
				}
			};
			popover.open(config);
		}
	},
	{
		name: t('Create_A_New_Channel'),
		icon: 'plus',
		condition: () => RocketChat.authz.hasAtLeastOnePermission(['create-c', 'create-p']),
		action: () => {
			menu.close();
			FlowRouter.go('create-channel');
		}
	},
	{
		name: t('Options'),
		icon: 'menu',
		condition: () => !(Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')),
		action: () => {
			let adminOption;
			if (RocketChat.authz.hasAtLeastOnePermission(['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) || (RocketChat.AdminBox.getOptions().length > 0)) {
				adminOption = {
					icon: 'customize',
					name: t('Administration'),
					type: 'open',
					id: 'administration',
					action: () => {
						SideNav.setFlex('adminFlex');
						SideNav.openFlex();
						FlowRouter.go('admin-info');
						popover.close();
					}
				};
			}

			const sidebarHeader = document.querySelector('.sidebar__header');
			const sidebarHeaderPadding = parseInt(getComputedStyle(sidebarHeader)['padding-left'].replace('px', '')) * 2;
			const sidebarHeaderMargin = parseInt(getComputedStyle(sidebarHeader)['margin-left'].replace('px', '')) * 2;

			const config = {
				popoverClass: 'sidebar-header',
				columns: [
					{
						groups: [
							{
								title: t('User'),
								items: [
									{
										icon: 'circle',
										name: t('Online'),
										modifier: 'online',
										action: () => setStatus('online')
									},
									{
										icon: 'circle',
										name: t('Away'),
										modifier: 'away',
										action: () => setStatus('away')
									},
									{
										icon: 'circle',
										name: t('Busy'),
										modifier: 'busy',
										action: () => setStatus('busy')
									},
									{
										icon: 'circle',
										name: t('Invisible'),
										modifier: 'offline',
										action: () => setStatus('offline')
									}
								]
							},
							{
								items: AccountBox.getItems().map(item => {
									let action;

									if (item.href) {
										action = () => {
											FlowRouter.go(item.href);
											popover.close();
										};
									}

									if (item.sideNav) {
										action = () => {
											SideNav.setFlex(item.sideNav);
											SideNav.openFlex();
											popover.close();
										};
									}

									return {
										icon: item.icon,
										name: t(item.name),
										type: 'open',
										id: item.name,
										href: item.href,
										sideNav: item.sideNav,
										action
									};
								}).concat([
									adminOption,
									{
										icon: 'user',
										name: t('My_Account'),
										type: 'open',
										id: 'account',
										action: () => {
											SideNav.setFlex('accountFlex');
											SideNav.openFlex();
											FlowRouter.go('account');
											popover.close();
										}
									},
									{
										icon: 'sign-out',
										name: t('Logout'),
										type: 'open',
										id: 'logout',
										action: () => {
											// const user = Meteor.user();
											Meteor.logout(() => {
												RocketChat.callbacks.run('afterLogoutCleanUp', user);
												Meteor.call('logoutCleanUp', user);
												FlowRouter.go('home');
												popover.close();
											});
										}
									}
								])
							}
						]
					}
				],
				position: {
					top: sidebarHeader.offsetHeight
				},
				customCSSProperties: {
					width: `${ sidebarHeader.offsetWidth - sidebarHeaderPadding + sidebarHeaderMargin }px`,
					left: isRtl() ? 'auto' : getComputedStyle(sidebarHeader)['padding-left'],
					right: isRtl() ? getComputedStyle(sidebarHeader)['padding-left'] : 'auto'
				}
			};

			popover.open(config);
		}
	}];
};
Template.sidebarHeader.helpers({
	myUserInfo() {
		if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
			return {
				username: 'anonymous',
				status: 'online'
			};
		}

		const user = Meteor.user() || {};
		const { username } = user;
		const userStatus = Session.get(`user_${ username }_status`);

		return {
			username,
			status: userStatus
		};
	},
	toolbarButtons() {
		return toolbarButtons(Meteor.user()).filter(button => !button.condition || button.condition());
	}
});

Template.sidebarHeader.events({
	'click .js-button'(e) {
		if (document.activeElement === e.currentTarget) {
			e.currentTarget.blur();
		}
		return this.action && this.action.apply(this, [e]);
	}
});
<|endoftext|>


<commit_before>// Copyright (c) 2015, Evan Summers (twitter.com/evanxsummers)
// ISC license, see http://github.com/evanx/redex/LICENSE

export function create(config, logger, context) {

   let that = {};

   logger.debug('config', config);

   config.services.forEach(service => {
      if (service.url) {
         if (!service.name) {
            service.name = service.url.replace(/^https?:\/\//, '');
            logger.debug('service.name', service.name);
         }
      }
      assert(service.url, 'service.url');
      assert(service.name, 'service.name');
      if (!service.label) {
         service.label = service.name;
      }
      context.stores.service.services.set(service.name, service);
      logger.debug('service', service);
   });

   async function checkServices() {
      for (const [name, service] of context.stores.service.services) {
         await checkService(service);
      }
   }

   async function checkService(service) {
      try {
         let content = await Requests.request({url: service.url, method: 'head', timeout: config.timeout});
         assert(lodash.isEmpty(content), 'empty content'); // HEAD request has empty content
         context.components.tracker.processStatus(service, 'OK');
      } catch (err) {
         if (!err.code || !err.statusCode) {
            logger.warn('checkService', service.name, err);
         }
         context.components.tracker.processStatus(service, 'WARN', err.message);
      }
   }

   const those = {
      async pub() {
         return null;
      },
      async start() {
         assert(config.interval, 'interval');
         assert(!lodash.isEmpty(config.services), 'services');
         logger.info('started', context.stores.service.services.size, config.interval);
         await checkServices();
         that.checkIntervalId = setInterval(checkServices, config.interval);
      },
      async end() {
         if (that.checkIntervalId) {
            clearInterval(that.checkIntervalId);
            delete that.checkIntervalId;
         }
      },
      async scheduledTimeout() {
      },
      async scheduledInterval() {
      }
   };

   return those;
}
<commit_msg>update<commit_after>// Copyright (c) 2015, Evan Summers (twitter.com/evanxsummers)
// ISC license, see http://github.com/evanx/redex/LICENSE

export function create(config, logger, context) {

   let that = {};

   logger.debug('config', config);

   config.services.forEach(service => {
      if (service.url) {
         if (!service.name) {
            service.name = service.url.replace(/^https?:\/\//, '');
            logger.debug('service.name', service.name);
         }
      }
      assert(service.url, 'service.url');
      assert(service.name, 'service.name');
      if (!service.label) {
         service.label = service.name;
      }
      context.stores.service.services.set(service.name, service);
      logger.debug('service', service);
   });

   async function checkServices() {
      for (const [name, service] of context.stores.service.services) {
         await checkService(service);
      }
   }

   async function checkService(service) {
      try {
         let content = await Requests.request({url: service.url, method: 'head', timeout: config.timeout});
         assert(lodash.isEmpty(content), 'empty content'); // HEAD request has empty content
         context.components.tracker.processStatus(service, 'OK');
      } catch (err) {
         if (!err.code && !err.statusCode) {
            logger.warn('checkService', service.name, err);
         }
         context.components.tracker.processStatus(service, 'WARN', err.message);
      }
   }

   const those = {
      async pub() {
         return null;
      },
      async start() {
         assert(config.interval, 'interval');
         assert(!lodash.isEmpty(config.services), 'services');
         logger.info('started', context.stores.service.services.size, config.interval);
         await checkServices();
         that.checkIntervalId = setInterval(checkServices, config.interval);
      },
      async end() {
         if (that.checkIntervalId) {
            clearInterval(that.checkIntervalId);
            delete that.checkIntervalId;
         }
      },
      async scheduledTimeout() {
      },
      async scheduledInterval() {
      }
   };

   return those;
}
<|endoftext|>


<commit_before>"use strict";
var createNamelist = require("./namelist");
var Html = require("./Html");
var Javascript = require("./Javascript");
const {
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
    skipSentenceQueue,
    rename,
    relink,
} = require("./common");

var compress = function (scoped, maped = Object.create(null)) {
    var { lets, vars, used } = scoped;
    var map = lets || vars;
    var __prevent = Object.create(null);
    for (var k in used) {
        if (!(k in map)) {
            if (k in maped) {
                k = maped[k];
            }
            __prevent[k] = true;
        }
    }
    var keys = Object.keys(map);
    keys.sort((a, b) => used[b].length - used[a].length);
    if (keys.length) {
        var names = createNamelist(keys.length, __prevent);
        for (var cx = 0, dx = keys.length; cx < dx; cx++) {
            var k = keys[cx];
            var name = names[cx];
            rename(used, k, name);
        }
    }
    if (scoped.length) {
        maped = Object.create(maped);
        for (var cx = 0, dx = keys.length; cx < dx; cx++) {
            var k = keys[cx];
            maped[k] = names[cx];
        }
        scoped.forEach(s => compress(s, maped));
    }
};

class Code extends Array {
    COMMENT = COMMENT
    SPACE = SPACE
    STRAP = STRAP
    STAMP = STAMP
    VALUE = VALUE
    QUOTED = QUOTED
    PIECE = PIECE
    EXPRESS = EXPRESS
    SCOPED = SCOPED
    LABEL = LABEL
    PROPERTY = PROPERTY
    pressed = false
    _scoped = null;
    helpcode = true;
    keepspace = true;
    /**
     * @type {Program}
     */
    program = null;
    isExpressQueue() {
        if (!this.first) return false;
        var first = this.first;
        if (first.type === SCOPED) {
            if (first.entry === '{') return false;
        }
        else if (first.type === STRAP) {
            if (!this.program.strapexp_reg.test(first.text)) return false;
        }
        else if (!~[EXPRESS, STAMP, QUOTED, SCOPED, VALUE].indexOf(first.type)) return false;
        var last = skipSentenceQueue(this.first);
        return this.last === last || !last;
    }

    toString() {
        return this.program.createString(this);
    }
    get envs() {
        return this.scoped.envs;
    }
    get vars() {
        return this.scoped.vars;
    }
    get used() {
        return this.scoped.used;
    }
    get yield() {
        return this.scoped.yield;
    }
    get async() {
        return this.scoped.async;
    }
    get await() {
        return this.scoped.await;
    }
    get return() {
        return this.scoped.return;
    }
    get scoped() {
        if (this._scoped) return this._scoped;
        return this._scoped = this.program.createScoped(this);
    }
    getUndecleared() {
        var res = Object.create(null);
        for (var k in this.envs) {
            res[k] = this.used[k];
        }
        return res;
    }
    // 提前处理属性
    break() {
        this.program.avoidMap = avoidMap;
        this.program.detour(this.first);
        return this;
    }
    // 绕开低版本ie的异常属性
    detour(ie) {
        this.program.avoidMap = avoidMap;
        this.program.detour(this.first, !!ie);
        return this;
    }
    // 压缩
    press(keepspace) {
        this.keepspace = keepspace;
        this.pressed = true;
        compress(this.scoped);
        return this;
    }
    relink(list = this) {
        return relink(list);
    }
}

var avoidMap = null;
function scan(text, type = "js", lastIndex = 0) {
    if (isFinite(type)) lastIndex = +type, type = arguments[1];
    var program;
    switch (type) {
        case "html":
            program = new Html;
            break;
        case "js":
        case "javascript":
            program = new Javascript;
            break;
        case "java":
            break;
    }
    program.Code = Code;
    program.lastIndex = lastIndex;
    var res = program.exec(text);
    res.program = program;
    return res;
}

Object.defineProperty(scan, "avoid", {
    get() {
        return avoidMap;
    },
    set(map) {
        avoidMap = map;
    }
});

scan.Code = scan.Program = Code;
module.exports = scan;<commit_msg>scanner2支持自定义解析器<commit_after>"use strict";
var createNamelist = require("./namelist");
var Html = require("./Html");
var Javascript = require("./Javascript");
const {
    /*-1 */COMMENT,
    /* 0 */SPACE,
    /* 1 */STRAP,
    /* 2 */STAMP,
    /* 3 */VALUE,
    /* 4 */QUOTED,
    /* 5 */PIECE,
    /* 6 */EXPRESS,
    /* 7 */SCOPED,
    /* 8 */LABEL,
    /* 9 */PROPERTY,
    skipSentenceQueue,
    rename,
    relink,
} = require("./common");

var compress = function (scoped, maped = Object.create(null)) {
    var { lets, vars, used } = scoped;
    var map = lets || vars;
    var __prevent = Object.create(null);
    for (var k in used) {
        if (!(k in map)) {
            if (k in maped) {
                k = maped[k];
            }
            __prevent[k] = true;
        }
    }
    var keys = Object.keys(map);
    keys.sort((a, b) => used[b].length - used[a].length);
    if (keys.length) {
        var names = createNamelist(keys.length, __prevent);
        for (var cx = 0, dx = keys.length; cx < dx; cx++) {
            var k = keys[cx];
            var name = names[cx];
            rename(used, k, name);
        }
    }
    if (scoped.length) {
        maped = Object.create(maped);
        for (var cx = 0, dx = keys.length; cx < dx; cx++) {
            var k = keys[cx];
            maped[k] = names[cx];
        }
        scoped.forEach(s => compress(s, maped));
    }
};

class Code extends Array {
    COMMENT = COMMENT
    SPACE = SPACE
    STRAP = STRAP
    STAMP = STAMP
    VALUE = VALUE
    QUOTED = QUOTED
    PIECE = PIECE
    EXPRESS = EXPRESS
    SCOPED = SCOPED
    LABEL = LABEL
    PROPERTY = PROPERTY
    pressed = false
    _scoped = null;
    helpcode = true;
    keepspace = true;
    /**
     * @type {Program}
     */
    program = null;
    isExpressQueue() {
        if (!this.first) return false;
        var first = this.first;
        if (first.type === SCOPED) {
            if (first.entry === '{') return false;
        }
        else if (first.type === STRAP) {
            if (!this.program.strapexp_reg.test(first.text)) return false;
        }
        else if (!~[EXPRESS, STAMP, QUOTED, SCOPED, VALUE].indexOf(first.type)) return false;
        var last = skipSentenceQueue(this.first);
        return this.last === last || !last;
    }

    toString() {
        return this.program.createString(this);
    }
    get envs() {
        return this.scoped.envs;
    }
    get vars() {
        return this.scoped.vars;
    }
    get used() {
        return this.scoped.used;
    }
    get yield() {
        return this.scoped.yield;
    }
    get async() {
        return this.scoped.async;
    }
    get await() {
        return this.scoped.await;
    }
    get return() {
        return this.scoped.return;
    }
    get scoped() {
        if (this._scoped) return this._scoped;
        return this._scoped = this.program.createScoped(this);
    }
    getUndecleared() {
        var res = Object.create(null);
        for (var k in this.envs) {
            res[k] = this.used[k];
        }
        return res;
    }
    // 提前处理属性
    break() {
        this.program.avoidMap = avoidMap;
        this.program.detour(this.first);
        return this;
    }
    // 绕开低版本ie的异常属性
    detour(ie) {
        this.program.avoidMap = avoidMap;
        this.program.detour(this.first, !!ie);
        return this;
    }
    // 压缩
    press(keepspace) {
        this.keepspace = keepspace;
        this.pressed = true;
        compress(this.scoped);
        return this;
    }
    relink(list = this) {
        return relink(list);
    }
}

var avoidMap = null;
function scan(text, type = "js", lastIndex = 0) {
    if (isFinite(type)) lastIndex = +type, type = arguments[1];
    var program;
    switch (type) {
        case "html":
            program = new Html;
            break;
        case "js":
        case "javascript":
            program = new Javascript;
            break;
        default:
            if (type instanceof Function) {
                program = new type;
            }
            break;
    }
    program.Code = Code;
    program.lastIndex = lastIndex;
    var res = program.exec(text);
    res.program = program;
    return res;
}

Object.defineProperty(scan, "avoid", {
    get() {
        return avoidMap;
    },
    set(map) {
        avoidMap = map;
    }
});

scan.Code = scan.Program = Code;
module.exports = scan;<|endoftext|>


<commit_before>'use strict';
var $ = require('../internals/export');
var addToUnscopables = require('../internals/add-to-unscopables');
var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer');
var lengthOfArrayLike = require('../internals/length-of-array-like');
var toAbsoluteIndex = require('../internals/to-absolute-index');
var toIndexedObject = require('../internals/to-indexed-object');
var toIntegerOrInfinity = require('../internals/to-integer-or-infinity');

var $Array = Array;
var max = Math.max;
var min = Math.min;

// `Array.prototype.toSpliced` method
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced
$({ target: 'Array', proto: true, arity: 2 }, {
  toSpliced: function toSpliced(start, deleteCount /* , ...items */) {
    var O = toIndexedObject(this);
    var len = lengthOfArrayLike(O);
    var actualStart = toAbsoluteIndex(start, len);
    var argumentsLength = arguments.length;
    var k = 0;
    var insertCount, actualDeleteCount, newLen, A;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min(max(toIntegerOrInfinity(deleteCount), 0), len - actualStart);
    }
    newLen = doesNotExceedSafeInteger(len + insertCount - actualDeleteCount);
    A = $Array(newLen);

    for (; k < actualStart; k++) A[k] = O[k];
    for (; k < actualStart + insertCount; k++) A[k] = arguments[k - actualStart + 2];
    for (; k < newLen; k++) A[k] = O[k + actualDeleteCount - insertCount];

    return A;
  }
});

addToUnscopables('toSpliced');
<commit_msg>drop an unnecessary option<commit_after>'use strict';
var $ = require('../internals/export');
var addToUnscopables = require('../internals/add-to-unscopables');
var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer');
var lengthOfArrayLike = require('../internals/length-of-array-like');
var toAbsoluteIndex = require('../internals/to-absolute-index');
var toIndexedObject = require('../internals/to-indexed-object');
var toIntegerOrInfinity = require('../internals/to-integer-or-infinity');

var $Array = Array;
var max = Math.max;
var min = Math.min;

// `Array.prototype.toSpliced` method
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced
$({ target: 'Array', proto: true }, {
  toSpliced: function toSpliced(start, deleteCount /* , ...items */) {
    var O = toIndexedObject(this);
    var len = lengthOfArrayLike(O);
    var actualStart = toAbsoluteIndex(start, len);
    var argumentsLength = arguments.length;
    var k = 0;
    var insertCount, actualDeleteCount, newLen, A;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min(max(toIntegerOrInfinity(deleteCount), 0), len - actualStart);
    }
    newLen = doesNotExceedSafeInteger(len + insertCount - actualDeleteCount);
    A = $Array(newLen);

    for (; k < actualStart; k++) A[k] = O[k];
    for (; k < actualStart + insertCount; k++) A[k] = arguments[k - actualStart + 2];
    for (; k < newLen; k++) A[k] = O[k + actualDeleteCount - insertCount];

    return A;
  }
});

addToUnscopables('toSpliced');
<|endoftext|>


<commit_before>import { merge, createObject } from "../htmlbars-util/object-utils";
import { validateChildMorphs, linkParams } from "../htmlbars-util/morph-utils";

/**
  Node classification:

  # Primary Statement Nodes:

  These nodes are responsible for a render node that represents a morph-range.

  * block
  * inline
  * content
  * element
  * component

  # Leaf Statement Nodes:

  This node is responsible for a render node that represents a morph-attr.

  * attribute

  # Expression Nodes:

  These nodes are not directly responsible for any part of the DOM, but are
  eventually passed to a Statement Node.

  * get
  * subexpr
  * concat
*/

var base = {
  acceptExpression: function(node, morph, env, scope) {
    var ret = { value: null };

    // Primitive literals are unambiguously non-array representations of
    // themselves.
    if (typeof node !== 'object' || node === null) {
      ret.value = node;
      return ret;
    }

    switch(node[0]) {
      // can be used by manualElement
      case 'value': ret.value = node[1]; break;
      case 'get': ret.value = this.get(node, morph, env, scope); break;
      case 'subexpr': ret.value = this.subexpr(node, morph, env, scope); break;
      case 'concat': ret.value = this.concat(node, morph, env, scope); break;
    }

    return ret;
  },

  acceptParamsAndHash: function(env, scope, morph, path, params, hash) {
    params = params && this.acceptParams(params, morph, env, scope);
    hash = hash && this.acceptHash(hash, morph, env, scope);

    linkParams(env, scope, morph, path, params, hash);
    return [params, hash];
  },

  acceptParams: function(nodes, morph, env, scope) {
    if (morph.linkedParams) {
      return morph.linkedParams.params;
    }

    var arr = new Array(nodes.length);

    for (var i=0, l=nodes.length; i<l; i++) {
      arr[i] =  this.acceptExpression(nodes[i], morph, env, scope, null, null).value;
    }

    return arr;
  },

  acceptHash: function(pairs, morph, env, scope) {
    if (morph.linkedParams) {
      return morph.linkedParams.hash;
    }

    var object = {};

    for (var i=0, l=pairs.length; i<l; i += 2) {
      object[pairs[i]] = this.acceptExpression(pairs[i+1], morph, env, scope, null, null).value;
    }

    return object;
  },

  // [ 'get', path ]
  get: function(node, morph, env, scope) {
    return env.hooks.get(env, scope, node[1]);
  },

  // [ 'subexpr', path, params, hash ]
  subexpr: function(node, morph, env, scope) {
    var path = node[1], params = node[2], hash = node[3];
    return env.hooks.subexpr(env, scope, path,
                             this.acceptParams(params, morph, env, scope),
                             this.acceptHash(hash, morph, env, scope));
  },

  // [ 'concat', parts ]
  concat: function(node, morph, env, scope) {
    return env.hooks.concat(env, this.acceptParams(node[1], morph, env, scope));
  }
};

export var AlwaysDirtyVisitor = merge(createObject(base), {
  // [ 'block', path, params, hash, templateId, inverseId ]
  block: function(node, morph, env, scope, template, visitor) {
    var path = node[1], params = node[2], hash = node[3], templateId = node[4], inverseId = node[5];
    var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.block(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1],
                           templateId === null ? null : template.templates[templateId],
                           inverseId === null ? null : template.templates[inverseId],
                           visitor);
  },

  // [ 'inline', path, params, hash ]
  inline: function(node, morph, env, scope, visitor) {
    var path = node[1], params = node[2], hash = node[3];
    var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.inline(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
  },

  // [ 'content', path ]
  content: function(node, morph, env, scope, visitor) {
    var path = node[1];

    morph.isDirty = morph.isSubtreeDirty = false;

    if (isHelper(env, scope, path)) {
      env.hooks.inline(morph, env, scope, path, [], {}, visitor);
      return;
    }

    var params;
    if (morph.linkedParams) {
      params = morph.linkedParams.params;
    } else {
      params = [env.hooks.get(env, scope, path)];
    }

    linkParams(env, scope, morph, '@range', params, null);
    env.hooks.range(morph, env, scope, path, params[0], visitor);
  },

  // [ 'element', path, params, hash ]
  element: function(node, morph, env, scope, visitor) {
    var path = node[1], params = node[2], hash = node[3];
    var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.element(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
  },

  // [ 'attribute', name, value ]
  attribute: function(node, morph, env, scope) {
    var name = node[1], value = node[2];
    var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, '@attribute', [value], null);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.attribute(morph, env, scope, name, paramsAndHash[0][0]);
  },

  // [ 'component', path, attrs, templateId, inverseId ]
  component: function(node, morph, env, scope, template, visitor) {
    var path = node[1], attrs = node[2], templateId = node[3], inverseId = node[4];
    var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, [], attrs);
    var templates = {
      default: template.templates[templateId],
      inverse: template.templates[inverseId]
    };

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.component(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1],
                        templates, visitor);
  },

  // [ 'attributes', template ]
  attributes: function(node, morph, env, scope, parentMorph, visitor) {
    let template = node[1];
    env.hooks.attributes(morph, env, scope, template, parentMorph, visitor);
  }
});

export default merge(createObject(base), {
  // [ 'block', path, params, hash, templateId, inverseId ]
  block: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.block(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'inline', path, params, hash ]
  inline: function(node, morph, env, scope, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.inline(node, morph, env, scope, visitor);
    });
  },

  // [ 'content', path ]
  content: function(node, morph, env, scope, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.content(node, morph, env, scope, visitor);
    });
  },

  // [ 'element', path, params, hash ]
  element: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.element(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'attribute', name, value ]
  attribute: function(node, morph, env, scope, template) {
    dirtyCheck(env, morph, null, function() {
      AlwaysDirtyVisitor.attribute(node, morph, env, scope, template);
    });
  },

  // [ 'component', path, attrs, templateId ]
  component: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.component(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'attributes', template ]
  attributes: function(node, morph, env, scope, parentMorph, visitor) {
    AlwaysDirtyVisitor.attributes(node, morph, env, scope, parentMorph, visitor);
  }
});

function dirtyCheck(_env, morph, visitor, callback) {
  var isDirty = morph.isDirty;
  var isSubtreeDirty = morph.isSubtreeDirty;
  var env = _env;

  if (isSubtreeDirty) {
    visitor = AlwaysDirtyVisitor;
  }

  if (isDirty || isSubtreeDirty) {
    callback(visitor);
  } else {
    if (morph.buildChildEnv) {
      env = morph.buildChildEnv(morph.state, env);
    }
    validateChildMorphs(env, morph, visitor);
  }
}

function isHelper(env, scope, path) {
  return (env.hooks.keywords[path] !== undefined) || env.hooks.hasHelper(env, scope, path);
}
<commit_msg>Rename acceptParamsAndHash to linkParamsAndHash<commit_after>import { merge, createObject } from "../htmlbars-util/object-utils";
import { validateChildMorphs, linkParams } from "../htmlbars-util/morph-utils";

/**
  Node classification:

  # Primary Statement Nodes:

  These nodes are responsible for a render node that represents a morph-range.

  * block
  * inline
  * content
  * element
  * component

  # Leaf Statement Nodes:

  This node is responsible for a render node that represents a morph-attr.

  * attribute

  # Expression Nodes:

  These nodes are not directly responsible for any part of the DOM, but are
  eventually passed to a Statement Node.

  * get
  * subexpr
  * concat
*/

var base = {
  acceptExpression: function(node, morph, env, scope) {
    var ret = { value: null };

    // Primitive literals are unambiguously non-array representations of
    // themselves.
    if (typeof node !== 'object' || node === null) {
      ret.value = node;
      return ret;
    }

    switch(node[0]) {
      // can be used by manualElement
      case 'value': ret.value = node[1]; break;
      case 'get': ret.value = this.get(node, morph, env, scope); break;
      case 'subexpr': ret.value = this.subexpr(node, morph, env, scope); break;
      case 'concat': ret.value = this.concat(node, morph, env, scope); break;
    }

    return ret;
  },

  acceptParams: function(nodes, morph, env, scope) {
    if (morph.linkedParams) {
      return morph.linkedParams.params;
    }

    var arr = new Array(nodes.length);

    for (var i=0, l=nodes.length; i<l; i++) {
      arr[i] =  this.acceptExpression(nodes[i], morph, env, scope, null, null).value;
    }

    return arr;
  },

  acceptHash: function(pairs, morph, env, scope) {
    if (morph.linkedParams) {
      return morph.linkedParams.hash;
    }

    var object = {};

    for (var i=0, l=pairs.length; i<l; i += 2) {
      object[pairs[i]] = this.acceptExpression(pairs[i+1], morph, env, scope, null, null).value;
    }

    return object;
  },

  // [ 'get', path ]
  get: function(node, morph, env, scope) {
    return env.hooks.get(env, scope, node[1]);
  },

  // [ 'subexpr', path, params, hash ]
  subexpr: function(node, morph, env, scope) {
    var path = node[1], params = node[2], hash = node[3];
    return env.hooks.subexpr(env, scope, path,
                             this.acceptParams(params, morph, env, scope),
                             this.acceptHash(hash, morph, env, scope));
  },

  // [ 'concat', parts ]
  concat: function(node, morph, env, scope) {
    return env.hooks.concat(env, this.acceptParams(node[1], morph, env, scope));
  },

  linkParamsAndHash: function(env, scope, morph, path, params, hash) {
    params = params && this.acceptParams(params, morph, env, scope);
    hash = hash && this.acceptHash(hash, morph, env, scope);

    linkParams(env, scope, morph, path, params, hash);
    return [params, hash];
  }
};

export var AlwaysDirtyVisitor = merge(createObject(base), {
  // [ 'block', path, params, hash, templateId, inverseId ]
  block: function(node, morph, env, scope, template, visitor) {
    var path = node[1], params = node[2], hash = node[3], templateId = node[4], inverseId = node[5];
    var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.block(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1],
                           templateId === null ? null : template.templates[templateId],
                           inverseId === null ? null : template.templates[inverseId],
                           visitor);
  },

  // [ 'inline', path, params, hash ]
  inline: function(node, morph, env, scope, visitor) {
    var path = node[1], params = node[2], hash = node[3];
    var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.inline(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
  },

  // [ 'content', path ]
  content: function(node, morph, env, scope, visitor) {
    var path = node[1];

    morph.isDirty = morph.isSubtreeDirty = false;

    if (isHelper(env, scope, path)) {
      env.hooks.inline(morph, env, scope, path, [], {}, visitor);
      return;
    }

    var params;
    if (morph.linkedParams) {
      params = morph.linkedParams.params;
    } else {
      params = [env.hooks.get(env, scope, path)];
    }

    linkParams(env, scope, morph, '@range', params, null);
    env.hooks.range(morph, env, scope, path, params[0], visitor);
  },

  // [ 'element', path, params, hash ]
  element: function(node, morph, env, scope, visitor) {
    var path = node[1], params = node[2], hash = node[3];
    var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.element(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
  },

  // [ 'attribute', name, value ]
  attribute: function(node, morph, env, scope) {
    var name = node[1], value = node[2];
    var paramsAndHash = this.linkParamsAndHash(env, scope, morph, '@attribute', [value], null);

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.attribute(morph, env, scope, name, paramsAndHash[0][0]);
  },

  // [ 'component', path, attrs, templateId, inverseId ]
  component: function(node, morph, env, scope, template, visitor) {
    var path = node[1], attrs = node[2], templateId = node[3], inverseId = node[4];
    var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, [], attrs);
    var templates = {
      default: template.templates[templateId],
      inverse: template.templates[inverseId]
    };

    morph.isDirty = morph.isSubtreeDirty = false;
    env.hooks.component(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1],
                        templates, visitor);
  },

  // [ 'attributes', template ]
  attributes: function(node, morph, env, scope, parentMorph, visitor) {
    let template = node[1];
    env.hooks.attributes(morph, env, scope, template, parentMorph, visitor);
  }
});

export default merge(createObject(base), {
  // [ 'block', path, params, hash, templateId, inverseId ]
  block: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.block(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'inline', path, params, hash ]
  inline: function(node, morph, env, scope, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.inline(node, morph, env, scope, visitor);
    });
  },

  // [ 'content', path ]
  content: function(node, morph, env, scope, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.content(node, morph, env, scope, visitor);
    });
  },

  // [ 'element', path, params, hash ]
  element: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.element(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'attribute', name, value ]
  attribute: function(node, morph, env, scope, template) {
    dirtyCheck(env, morph, null, function() {
      AlwaysDirtyVisitor.attribute(node, morph, env, scope, template);
    });
  },

  // [ 'component', path, attrs, templateId ]
  component: function(node, morph, env, scope, template, visitor) {
    dirtyCheck(env, morph, visitor, function(visitor) {
      AlwaysDirtyVisitor.component(node, morph, env, scope, template, visitor);
    });
  },

  // [ 'attributes', template ]
  attributes: function(node, morph, env, scope, parentMorph, visitor) {
    AlwaysDirtyVisitor.attributes(node, morph, env, scope, parentMorph, visitor);
  }
});

function dirtyCheck(_env, morph, visitor, callback) {
  var isDirty = morph.isDirty;
  var isSubtreeDirty = morph.isSubtreeDirty;
  var env = _env;

  if (isSubtreeDirty) {
    visitor = AlwaysDirtyVisitor;
  }

  if (isDirty || isSubtreeDirty) {
    callback(visitor);
  } else {
    if (morph.buildChildEnv) {
      env = morph.buildChildEnv(morph.state, env);
    }
    validateChildMorphs(env, morph, visitor);
  }
}

function isHelper(env, scope, path) {
  return (env.hooks.keywords[path] !== undefined) || env.hooks.hasHelper(env, scope, path);
}
<|endoftext|>


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

    var app = angular.module('ui.tinymce');

    // If you want to cutomize uiTinymceConfig for your theme, please copy this file to you theme in the
    // same path (static/js/). This are the default setting for timtec
    app.value('uiTinymceConfig', {
        base_url: '/static/tinymce-dist/',
        related_url: true,
        inline: false,
        menubar: false,
        relative_urls: false,
        plugins : 'advlist lists autolink link image media autoresize',
        toolbar: 'bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | quicklink link image media fullscreen',
        skin: 'lightgray',
        theme : 'modern',
        language: 'pt_BR',
        language_url : '/static/vendor/tinymce/langs/pt_BR.js',
        resize: true,
        elementpath: false,

        // media customizations
        media_poster: false,
        media_alt_source: false,
        media_dimensions: false,
        media_url_resolver: function (data, resolve/*, reject*/) {
            var complete_url = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
            var result = complete_url.exec(data.url);
            if (result && result[2].length == 11) {
                var youtube_id = result[2];
                var embedHtml = '';
                resolve({html: embedHtml});
            } else {
                resolve({html: ''});
            }
        },

        // Image upload
        // enable title field in the Image dialog
        image_title: false,
        image_description: false,
        image_dimensions: false,
        // enable automatic uploads of images represented by blob or data URIs
        automatic_uploads: true,
        // here we add custom filepicker only to Image dialog
        file_picker_types: 'image',
        // and here's our custom image picker
        file_picker_callback: function(cb, value, meta) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');

            // Note: In modern browsers input[type="file"] is functional without
            // even adding it to the DOM, but that might not be the case in some older
            // or quirky browsers like IE, so you might want to add it to the DOM
            // just in case, and visually hide it. And do not forget do remove it
            // once you do not need it anymore.
            document.body.appendChild(input);

            input.onchange = function() {
                var file = this.files[0];

                // Note: Now we need to register the blob in TinyMCEs image blob
                // registry. In the next release this part hopefully won't be
                // necessary, as we are looking to handle it internally.
                var id = 'blobid' + (new Date()).getTime();
                var blobCache = tinymce.activeEditor.editorUpload.blobCache;
                var blobInfo = blobCache.create(id, file);
                blobCache.add(blobInfo);

                // call the callback and populate the Title field with the file name
                cb(blobInfo.blobUri(), { title: file.name });
            };

            input.click();
          }
    });

})(window.angular);
<commit_msg>Impede que o campo de entrada de arquivos criado pelo TinyMCE interfira no layout<commit_after>(function(angular){
    'use strict';

    var app = angular.module('ui.tinymce');

    // If you want to cutomize uiTinymceConfig for your theme, please copy this file to you theme in the
    // same path (static/js/). This are the default setting for timtec
    app.value('uiTinymceConfig', {
        base_url: '/static/tinymce-dist/',
        related_url: true,
        inline: false,
        menubar: false,
        relative_urls: false,
        plugins : 'advlist lists autolink link image media autoresize',
        toolbar: 'bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | quicklink link image media fullscreen',
        skin: 'lightgray',
        theme : 'modern',
        language: 'pt_BR',
        language_url : '/static/vendor/tinymce/langs/pt_BR.js',
        resize: true,
        elementpath: false,

        // media customizations
        media_poster: false,
        media_alt_source: false,
        media_dimensions: false,
        media_url_resolver: function (data, resolve/*, reject*/) {
            var complete_url = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
            var result = complete_url.exec(data.url);
            if (result && result[2].length == 11) {
                var youtube_id = result[2];
                var embedHtml = '';
                resolve({html: embedHtml});
            } else {
                resolve({html: ''});
            }
        },

        // Image upload
        // enable title field in the Image dialog
        image_title: false,
        image_description: false,
        image_dimensions: false,
        // enable automatic uploads of images represented by blob or data URIs
        automatic_uploads: true,
        // here we add custom filepicker only to Image dialog
        file_picker_types: 'image',
        // and here's our custom image picker
        file_picker_callback: function(cb, value, meta) {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.setAttribute('accept', 'image/*');
            input.style.display = 'none';

            // Note: In modern browsers input[type="file"] is functional without
            // even adding it to the DOM, but that might not be the case in some older
            // or quirky browsers like IE, so you might want to add it to the DOM
            // just in case, and visually hide it. And do not forget do remove it
            // once you do not need it anymore.
            document.body.appendChild(input);

            input.onchange = function() {
                var file = this.files[0];

                // Note: Now we need to register the blob in TinyMCEs image blob
                // registry. In the next release this part hopefully won't be
                // necessary, as we are looking to handle it internally.
                var id = 'blobid' + (new Date()).getTime();
                var blobCache = tinymce.activeEditor.editorUpload.blobCache;
                var blobInfo = blobCache.create(id, file);
                blobCache.add(blobInfo);

                // call the callback and populate the Title field with the file name
                cb(blobInfo.blobUri(), { title: file.name });
            };

            input.click();
          }
    });

})(window.angular);
<|endoftext|>


<commit_before>export const VRecDialog = new class {
	static initClass() {
		this.prototype.opened = false;
		this.prototype.initiated = false;
		this.prototype.width = 400;
		this.prototype.height = 280;
	}

	init() {
		if (this.initiated) {
			return;
		}

		this.initiated = true;
		return Blaze.render(Template.vrecDialog, document.body);
	}

	open(source) {
		if (!this.initiated) {
			this.init();
		}

		this.source = source;
		const dialog = $('.vrec-dialog');
		this.setPosition(dialog, source);
		dialog.addClass('show');
		this.opened = true;

		return this.initializeCamera();
	}

	close() {
		$('.vrec-dialog').removeClass('show');
		this.opened = false;

		if (this.video != null) {
			return VideoRecorder.stop();
		}
	}

	setPosition(dialog, source) {
		const sourcePos = $(source).offset();
		let left = (sourcePos.left - this.width) + 100;
		let top = sourcePos.top - this.height - 40;

		if (left < 0) {
			left = 10;
		}
		if (top < 0) {
			top = 10;
		}

		return dialog.css({ top: `${ top }px`, left: `${ left }px` });
	}

	initializeCamera() {
		this.video = $('.vrec-dialog video').get('0');
		if (!this.video) {
			return;
		}
		return VideoRecorder.start(this.video);
	}
};
<commit_msg>fix vrecdialog constructor<commit_after>export const VRecDialog = new class {
	constructor() {
		this.opened = false;
		this.initiated = false;
		this.width = 400;
		this.height = 280;
	}

	init() {
		if (this.initiated) {
			return;
		}

		this.initiated = true;
		return Blaze.render(Template.vrecDialog, document.body);
	}

	open(source) {
		if (!this.initiated) {
			this.init();
		}

		this.source = source;
		const dialog = $('.vrec-dialog');
		this.setPosition(dialog, source);
		dialog.addClass('show');
		this.opened = true;

		return this.initializeCamera();
	}

	close() {
		$('.vrec-dialog').removeClass('show');
		this.opened = false;

		if (this.video != null) {
			return VideoRecorder.stop();
		}
	}

	setPosition(dialog, source) {
		const sourcePos = $(source).offset();
		let left = (sourcePos.left - this.width) + 100;
		let top = sourcePos.top - this.height - 40;

		if (left < 0) {
			left = 10;
		}
		if (top < 0) {
			top = 10;
		}

		return dialog.css({ top: `${ top }px`, left: `${ left }px` });
	}

	initializeCamera() {
		this.video = $('.vrec-dialog video').get('0');
		if (!this.video) {
			return;
		}
		return VideoRecorder.start(this.video);
	}
};
<|endoftext|>


<commit_before>import { Connectors } from 'meteor/vulcan:core'; // import from vulcan:lib because vulcan:core isn't loaded yet
import Users from 'meteor/vulcan:users';
import Votes from './votes/collection.js';

Users.addField([
  /**
    An array containing votes
  */
  {
    fieldName: 'votes',
    fieldSchema: {
      type: Array,
      optional: true,
      viewableBy: Users.owns,
      resolveAs: {
        type: '[Vote]',
        arguments: 'collectionName: String',
        resolver: async (user, args, context) => {
          const selector = {userId: user._id};
          if (args.collectionName) {
            selector.collectionName = args.collectionName;
          }
          const votes = await Connectors.find(Votes, selector);
          return Users.restrictViewableFields(currentUser, Votes, votes);
        }
      },
    }
  },
  {
    fieldName: 'votes.$',
    fieldSchema: {
      type: Object,
      optional: true
    }
  },
]);
<commit_msg>Fix user reference<commit_after>import { Connectors } from 'meteor/vulcan:core'; // import from vulcan:lib because vulcan:core isn't loaded yet
import Users from 'meteor/vulcan:users';
import Votes from './votes/collection.js';

Users.addField([
  /**
    An array containing votes
  */
  {
    fieldName: 'votes',
    fieldSchema: {
      type: Array,
      optional: true,
      viewableBy: Users.owns,
      resolveAs: {
        type: '[Vote]',
        arguments: 'collectionName: String',
        resolver: async (user, args, context) => {
          const selector = {userId: user._id};
          if (args.collectionName) {
            selector.collectionName = args.collectionName;
          }
          const votes = await Connectors.find(Votes, selector);
          return Users.restrictViewableFields(user, Votes, votes);
        }
      },
    }
  },
  {
    fieldName: 'votes.$',
    fieldSchema: {
      type: Object,
      optional: true
    }
  },
]);
<|endoftext|>


<commit_before>'use strict';

var assign          = require('es5-ext/object/assign')
  , setPrototypeOf  = require('es5-ext/object/set-prototype-of')
  , d               = require('d')
  , lazy            = require('d/lazy')
  , Observable      = require('observable-value')
  , ReadOnly        = require('observable-value/create-read-only')(Observable)
  , proto           = require('../_observable')
  , accessCollector = require('../access-collector')

  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , valueDesc = Object.getOwnPropertyDescriptor(Observable.prototype, 'value')
  , getValue = valueDesc.get
  , ObservableProperty, accessSniff;

module.exports = ObservableProperty = function (object, sKey) {
	var getter, value;
	defineProperties(this, {
		object: d('', object),
		key: d('', object._keys_[sKey]),
		dbId: d('', object.__id__ + '/' + sKey),
		__sKey__: d('', sKey)
	});
	if (object.isKeyStatic(this.key)) {
		value = object[this.key];
	} else {
		getter = object._resolveGetter_(sKey);
		value = getter ? object._getDynamicValue_(sKey).resolvedValue : object._resolve_(sKey);
	}
	Observable.call(this, value);
	object._observableProperties_[sKey] = this;
};
setPrototypeOf(ObservableProperty, Observable);

ObservableProperty.prototype = Object.create(proto, assign({
	constructor: d(ObservableProperty),
	dbKind: d('observableProperty'),
	value: d.gs('', function () {
		if (!accessSniff && !this.object.__prototypeTurnInProgress__) return getValue.call(this);
		return this.object._resolve_(this.__sKey__);
	}, function (value) {
		var object = this.object, sKey = this.__sKey__;
		object._set_(sKey, object._validateSet_(sKey, value));
	}),
	lastModified: d.gs(function () {
		if (this.__lastModified__ == null) {
			this.__lastModified__ =
				this.object._getPropertyLastModified_(this.__sKey__);
		}
		return this.__lastModified__;
	}),
	descriptor: d.gs(function () {
		return this.object._getDescriptor_(this.__sKey__);
	})
}, lazy({
	ownDescriptor: d(function () {
		var desc = this.object._getOwnDescriptor_(this.__sKey__);
		defineProperty(this, 'descriptor', d('', desc));
		return desc;
	}, { desc: '' }),
	_lastModified: d(function () {
		var observable = new ReadOnly(this.lastModified);
		this.on('change', function () {
			observable._setValue(this.__lastModified__);
		});
		return observable;
	})
})));

accessCollector.on('register', function (value) { accessSniff = value; });
accessCollector.on('unregister', function (value) { accessSniff = null; });
<commit_msg>Fix reactive resolution of lastModified<commit_after>'use strict';

var assign          = require('es5-ext/object/assign')
  , setPrototypeOf  = require('es5-ext/object/set-prototype-of')
  , d               = require('d')
  , lazy            = require('d/lazy')
  , Observable      = require('observable-value')
  , ReadOnly        = require('observable-value/create-read-only')(Observable)
  , proto           = require('../_observable')
  , accessCollector = require('../access-collector')

  , defineProperty = Object.defineProperty
  , defineProperties = Object.defineProperties
  , valueDesc = Object.getOwnPropertyDescriptor(Observable.prototype, 'value')
  , getValue = valueDesc.get
  , ObservableProperty, accessSniff;

module.exports = ObservableProperty = function (object, sKey) {
	var getter, value;
	defineProperties(this, {
		object: d('', object),
		key: d('', object._keys_[sKey]),
		dbId: d('', object.__id__ + '/' + sKey),
		__sKey__: d('', sKey)
	});
	if (object.isKeyStatic(this.key)) {
		value = object[this.key];
	} else {
		getter = object._resolveGetter_(sKey);
		value = getter ? object._getDynamicValue_(sKey).resolvedValue : object._resolve_(sKey);
	}
	Observable.call(this, value);
	object._observableProperties_[sKey] = this;
};
setPrototypeOf(ObservableProperty, Observable);

ObservableProperty.prototype = Object.create(proto, assign({
	constructor: d(ObservableProperty),
	dbKind: d('observableProperty'),
	value: d.gs('', function () {
		if (!accessSniff && !this.object.__prototypeTurnInProgress__) return getValue.call(this);
		return this.object._resolve_(this.__sKey__);
	}, function (value) {
		var object = this.object, sKey = this.__sKey__;
		object._set_(sKey, object._validateSet_(sKey, value));
	}),
	lastModified: d.gs(function () {
		if (this.__lastModified__ == null) {
			this.__lastModified__ =
				this.object._getPropertyLastModified_(this.__sKey__);
		}
		return this.__lastModified__;
	}),
	descriptor: d.gs(function () {
		return this.object._getDescriptor_(this.__sKey__);
	})
}, lazy({
	ownDescriptor: d(function () {
		var desc = this.object._getOwnDescriptor_(this.__sKey__);
		defineProperty(this, 'descriptor', d('', desc));
		return desc;
	}, { desc: '' }),
	_lastModified: d(function () {
		var observable = new ReadOnly(this.lastModified), onUpdate;
		this.on('change', onUpdate = function () { observable._setValue(this.__lastModified__); });
		this.ownDescriptor.on('selfupdate', onUpdate);
		return observable;
	})
})));

accessCollector.on('register', function (value) { accessSniff = value; });
accessCollector.on('unregister', function (value) { accessSniff = null; });
<|endoftext|>


<commit_before>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Create Embed Message",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Embed Message",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	return `${data.title}`;
},

//---------------------------------------------------------------------
	 // DBM Mods Manager Variables (Optional but nice to have!)
	 //
	 // These are variables that DBM Mods Manager uses to show information
	 // about the mods for people to see in the list.
	 //---------------------------------------------------------------------

	 // Who made the mod (If not set, defaults to "DBM Mods")
	 author: "DBM, ZockerNico",

	 // The version of the mod (Defaults to 1.0.0)
	 version: "1.9.5",//Added in 1.8.2

	 // A short description to show on the mod line for this mod (Must be on a single line)
	 short_description: "Changed category, remove timestamp option and added author url.",

	 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

	 //---------------------------------------------------------------------

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage);
	if(type !== varType) return;
	return ([data.varName, 'Embed Message']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["title", "author", "color", "url", "authorIcon", "authorUrl", "imageUrl", "thumbUrl", "storage", "varName"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

		This action has been modified by DBM Mods.

	Title:

	<input id="title" class="round" type="text">

	Author Name:

	<input id="author" class="round" type="text" placeholder="Leave blank to disallow author!">

	Author Icon URL:

	<input id="authorIcon" class="round" type="text" placeholder="Leave blank for none!">

	Author URL:

	<input id="authorUrl" class="round" type="text" placeholder="Leave blank for none!">

	Color:

	<input id="color" class="round" type="text" placeholder="Leave blank for default!">

	URL:

	<input id="url" class="round" type="text" placeholder="Leave blank for none!">

	Image URL:

	<input id="imageUrl" class="round" type="text" placeholder="Leave blank for none!">

	Thumbnail URL:

	<input id="thumbUrl" class="round" type="text" placeholder="Leave blank for none!">

		Store In:

		<select id="storage" class="round">
			${data.variables[1]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text">

`
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const embed = this.createEmbed();
	embed.setTitle(this.evalMessage(data.title, cache));
	if(data.url) {
		embed.setURL(this.evalMessage(data.url, cache));
	};
	if(data.author) {
		if(data.authorIcon && data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), this.evalMessage(data.authorIcon, cache), this.evalMessage(data.authorUrl, cache));
		} else if(data.authorIcon && !data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), this.evalMessage(data.authorIcon));
		} else if(!data.authorIcon && data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), '', this.evalMessage(data.authorUrl, cache));
		} else {
			embed.setAuthor(this.evalMessage(data.author, cache));
		};
	};
	if(data.color) {
		embed.setColor(this.evalMessage(data.color, cache));
	};
	if(data.imageUrl) {
		embed.setImage(this.evalMessage(data.imageUrl, cache));
	};
	if(data.thumbUrl) {
		embed.setThumbnail(this.evalMessage(data.thumbUrl, cache));
	};
	const storage = parseInt(data.storage);
	const varName = this.evalMessage(data.varName, cache);
	this.storeValue(embed, storage, varName, cache);
	this.callNextAction(cache);
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
	const DiscordJS = DBM.DiscordJS;
	const Actions = DBM.Actions;

	Actions.createEmbed = function() {
		return new DiscordJS.RichEmbed();
	};
}

}; // End of module
<commit_msg>Fixed TypeError<commit_after>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Create Embed Message",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Embed Message",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	return `${data.title}`;
},

//---------------------------------------------------------------------
	 // DBM Mods Manager Variables (Optional but nice to have!)
	 //
	 // These are variables that DBM Mods Manager uses to show information
	 // about the mods for people to see in the list.
	 //---------------------------------------------------------------------

	 // Who made the mod (If not set, defaults to "DBM Mods")
	 author: "DBM, ZockerNico",

	 // The version of the mod (Defaults to 1.0.0)
	 version: "1.9.5",//Added in 1.8.2

	 // A short description to show on the mod line for this mod (Must be on a single line)
	 short_description: "Changed category, remove timestamp option and added author url.",

	 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

	 //---------------------------------------------------------------------

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage);
	if(type !== varType) return;
	return ([data.varName, 'Embed Message']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["title", "author", "color", "url", "authorIcon", "authorUrl", "imageUrl", "thumbUrl", "storage", "varName"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

		This action has been modified by DBM Mods.

	Title:

	<input id="title" class="round" type="text">

	Author Name:

	<input id="author" class="round" type="text" placeholder="Leave blank to disallow author!">

	Author Icon URL:

	<input id="authorIcon" class="round" type="text" placeholder="Leave blank for none!">

	Author URL:

	<input id="authorUrl" class="round" type="text" placeholder="Leave blank for none!">

	Color:

	<input id="color" class="round" type="text" placeholder="Leave blank for default!">

	URL:

	<input id="url" class="round" type="text" placeholder="Leave blank for none!">

	Image URL:

	<input id="imageUrl" class="round" type="text" placeholder="Leave blank for none!">

	Thumbnail URL:

	<input id="thumbUrl" class="round" type="text" placeholder="Leave blank for none!">

		Store In:

		<select id="storage" class="round">
			${data.variables[1]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text">

`
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const embed = this.createEmbed();
	embed.setTitle(this.evalMessage(data.title, cache));
	if(data.url) {
		embed.setURL(this.evalMessage(data.url, cache));
	};
	if(data.author) {
		if(data.authorIcon && data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), this.evalMessage(data.authorIcon, cache), this.evalMessage(data.authorUrl, cache));
		} else if(data.authorIcon && !data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), this.evalMessage(data.authorIcon, cache));
		} else if(!data.authorIcon && data.authorUrl) {
			embed.setAuthor(this.evalMessage(data.author, cache), '', this.evalMessage(data.authorUrl, cache));
		} else {
			embed.setAuthor(this.evalMessage(data.author, cache));
		};
	};
	if(data.color) {
		embed.setColor(this.evalMessage(data.color, cache));
	};
	if(data.imageUrl) {
		embed.setImage(this.evalMessage(data.imageUrl, cache));
	};
	if(data.thumbUrl) {
		embed.setThumbnail(this.evalMessage(data.thumbUrl, cache));
	};
	const storage = parseInt(data.storage);
	const varName = this.evalMessage(data.varName, cache);
	this.storeValue(embed, storage, varName, cache);
	this.callNextAction(cache);
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
	const DiscordJS = DBM.DiscordJS;
	const Actions = DBM.Actions;

	Actions.createEmbed = function() {
		return new DiscordJS.RichEmbed();
	};
}

}; // End of module
<|endoftext|>