<commit_before>import $ from 'jquery';
import TableDetailComponent from '../../../js/TableDetailComponent'

describe('TableDetailComponent', () => {
	let clickEvent;
	let keyDownEvent = $.Event('keydown');
	let tabKeyDownEvent = $.Event('keydown');
	let $html;
	let $body;
	let $tableHTML;
	let tableDetailComponent;
	let tableDetailComponentWithoutHTML;

	beforeEach(() => {
		$html = $('html');
		$body = $('body');

		$tableHTML = $(
			'
' +
			'
' +
			'		Actions	' +
			'
' +
			'
' +
			'		<tr class="parent" data-table-detail-content="
content
<form><button>button</button></form>" data-table-detail-panel-custom-title="custom panel title">' +
			'			Details	' +
			'
' +
			'
' +
			'			Details	' +
			'
' +
			'
' +
			'
'
		).appendTo($body);

		clickEvent = $.Event('click');

		tableDetailComponent = new TableDetailComponent($html);
	});

	afterEach(() => {
        $body.empty();

        $html.off('keydown');
    });

    describe('init()', () => {
		it('should throw an error if $html isn’t passed to the component', () => {
			tableDetailComponentWithoutHTML = new TableDetailComponent(undefined);

			expect(() => {
                tableDetailComponentWithoutHTML.init($body);
            }).to.throw('$html must be passed to TableDetailComponent');
		});

		it('should not add the backdrop if data-table-detail-table attribute is not present', () => {
			$body.find('[data-table-detail-table]').removeAttr('data-table-detail-table');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail-backdrop')).to.have.length(0);
		});

		it('should not add the panel markup if data-table-detail-table attribute is not present', () => {
			$body.find('[data-table-detail-table]').removeAttr('data-table-detail-table');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(0);
		});

		it('should not add the detail panel to the DOM if a panel is already present', () => {
			$body.append('

');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(1);
		});

		it('should add the detail panel to the body if no main elements are present', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(1);
		});

		it('should add the backdrop to the body if no main elements are present', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail-backdrop')).to.have.length(1);
		});

		it('should append the panel to the  element if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('');

			tableDetailComponent.init($body);

			expect($body.find('main [data-table-detail-panel]')).to.have.length(1);
		});

		it('should append the backdrop to the  element if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('');

			tableDetailComponent.init($body);

			expect($body.find('main .table-detail-backdrop')).to.have.length(1);
		});

		it('should append the panel to the element with role="main" if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('

');

			tableDetailComponent.init($body);

			expect($body.find('[role="main"] [data-table-detail-panel]')).to.have.length(1);
		});

		it('should append the backdrop to the element with role="main" if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('

');

			tableDetailComponent.init($body);

			expect($body.find('[role="main"] .table-detail-backdrop')).to.have.length(1);
		});
	});

	describe('When the panel is added', () => {
		it('should have the role="dialog" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[role="dialog"]')).to.have.length(1);
		});

		it('should have the aria-modal="true" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[aria-modal="true"]')).to.have.length(1);
		});

		it('should have the aria-hidden="true" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[aria-hidden="true"]')).to.have.length(1);
		});

		it('should have the tabindex attribute on the close button', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail__header-close[tabindex="-1"]')).to.have.length(1);
		});
	});

	describe('When the view panel link is clicked', () => {
		it('should prevent the default behaviour of the click', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect(clickEvent.isDefaultPrevented()).to.be.true;
		});

		it('should set a custom panel title if one is set', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-title]').text()).to.equal('custom panel title');
		});

		it('should empty the panel body and replace the content', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-panel-body]').append('some content to be removed');

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body]').html()).to.equal('
content
<form><button>button</button></form>');
		});

		it('should add the "in" class to the backdrop to show it', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.true;
		});

		it('should add the "table-detail--open" class to the panel to open it', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.true;
		});

		it('should focus the close button if there is no other focusable element in the panel', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-content]').attr('data-table-detail-content', '
Content
')

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-close-panel]').is(':focus')).to.be.true;
		});

		it('should focus the first focusable element if one is present ', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] form button').is(':focus')).to.be.true;
		});
	});

	describe('When the view panel link is clicked from the child row', () => {
		it('should fetch the panel title from the parent row', () => {
			tableDetailComponent.init($body);

			$body.find('.child [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-title]').text()).to.equal('custom panel title');
		});

		it('should empty the panel body and replace the content', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-panel-body]').append('some content to be removed');

			$body.find('.child [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body]').html()).to.equal('
content
<form><button>button</button></form>');
		});
	});

	describe('when the panel is open and tab is pressed', () => {
		beforeEach(() => {
			tabKeyDownEvent.keyCode = 9;
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-view-detail="true"]').trigger(clickEvent);
		});

		it('should focus the first element, when the last element was previously focused', () => {
			$body.find('.table-detail--open .table-detail__body form button').focus();

			$html.trigger(tabKeyDownEvent);

			expect($body.find('.table-detail--open .table-detail__header-close').is(':focus')).to.be.true;
		});
	});

	describe('when the panel is open and shift + tab is pressed', () => {
		beforeEach(() => {
			tabKeyDownEvent.keyCode = 9;
			tabKeyDownEvent.shiftKey = true;
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-view-detail="true"]').trigger(clickEvent);
		});

		it('should focus the last element, when the first element was previously focused', () => {
			$body.find('.table-detail--open .table-detail__header-close').focus();

			$html.trigger(tabKeyDownEvent);

			expect($body.find('.table-detail--open .table-detail__body form button').is(':focus')).to.be.true;
		});
	});

	describe('When the close panel button is clicked', () => {
		it('should remove the "in" class from the backdrop to hide it', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('should remove the "table-detail--open" class from the panel', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});

		it('should add tabindex="-1" to all focusable elements', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] button').attr('tabindex')).to.equal('-1');
			expect($body.find('[data-table-detail-close-panel]').attr('tabindex')).to.equal('-1');
		});
	});

	describe('When the panel is opened and closed', () => {
		it('should not be possible to focus elements in the panel', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] button').attr('tabindex')).to.equal('-1');
			expect($body.find('[data-table-detail-close-panel]').attr('tabindex')).to.equal('-1');
		});

		it('should add the aria-hidden="true" attribute to the panel', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('.table-detail[aria-hidden="true"]')).to.have.length(1);
		});
	});

	describe('When the ESC key is pressed', () => {
		beforeEach(() => {
			keyDownEvent.keyCode = 27;
			tableDetailComponent.init($body);
			$body.find('table [data-table-detail-view-detail="true"]').trigger(clickEvent);
			$html.trigger(keyDownEvent);
		});

		it('should remove the "in" class from the backdrop to hide it', () => {
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('remove the "table-detail--open" class to the panel to close it', () => {
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});
	});

	describe('When the backdrop overlay is clicked', () => {
		it('should remove the "in" class from the backdrop to hide it', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.true;

			$body.find('.table-detail-backdrop').trigger(clickEvent);
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('should remove the "table-detail--open" class from the panel to close it', () => {
			tableDetailComponent.init($body);

			$body.find('[data-table-detail-view-detail]').trigger(clickEvent);
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.true;

			$body.find('.table-detail-backdrop').trigger(clickEvent);
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});
	});
});
<commit_msg>For clarity, point existing detail triggers at the parent row<commit_after>import $ from 'jquery';
import TableDetailComponent from '../../../js/TableDetailComponent'

describe('TableDetailComponent', () => {
	let clickEvent;
	let keyDownEvent = $.Event('keydown');
	let tabKeyDownEvent = $.Event('keydown');
	let $html;
	let $body;
	let $tableHTML;
	let tableDetailComponent;
	let tableDetailComponentWithoutHTML;

	beforeEach(() => {
		$html = $('html');
		$body = $('body');

		$tableHTML = $(
			'
' +
			'
' +
			'		Actions	' +
			'
' +
			'
' +
			'		<tr class="parent" data-table-detail-content="
content
<form><button>button</button></form>" data-table-detail-panel-custom-title="custom panel title">' +
			'			Details	' +
			'
' +
			'
' +
			'			Details	' +
			'
' +
			'
' +
			'
'
		).appendTo($body);

		clickEvent = $.Event('click');

		tableDetailComponent = new TableDetailComponent($html);
	});

	afterEach(() => {
        $body.empty();

        $html.off('keydown');
    });

    describe('init()', () => {
		it('should throw an error if $html isn’t passed to the component', () => {
			tableDetailComponentWithoutHTML = new TableDetailComponent(undefined);

			expect(() => {
                tableDetailComponentWithoutHTML.init($body);
            }).to.throw('$html must be passed to TableDetailComponent');
		});

		it('should not add the backdrop if data-table-detail-table attribute is not present', () => {
			$body.find('[data-table-detail-table]').removeAttr('data-table-detail-table');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail-backdrop')).to.have.length(0);
		});

		it('should not add the panel markup if data-table-detail-table attribute is not present', () => {
			$body.find('[data-table-detail-table]').removeAttr('data-table-detail-table');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(0);
		});

		it('should not add the detail panel to the DOM if a panel is already present', () => {
			$body.append('

');

			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(1);
		});

		it('should add the detail panel to the body if no main elements are present', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail')).to.have.length(1);
		});

		it('should add the backdrop to the body if no main elements are present', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail-backdrop')).to.have.length(1);
		});

		it('should append the panel to the  element if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('');

			tableDetailComponent.init($body);

			expect($body.find('main [data-table-detail-panel]')).to.have.length(1);
		});

		it('should append the backdrop to the  element if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('');

			tableDetailComponent.init($body);

			expect($body.find('main .table-detail-backdrop')).to.have.length(1);
		});

		it('should append the panel to the element with role="main" if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('

');

			tableDetailComponent.init($body);

			expect($body.find('[role="main"] [data-table-detail-panel]')).to.have.length(1);
		});

		it('should append the backdrop to the element with role="main" if one is present', () => {
			$body.find('[data-table-detail-table]').wrap('

');

			tableDetailComponent.init($body);

			expect($body.find('[role="main"] .table-detail-backdrop')).to.have.length(1);
		});
	});

	describe('When the panel is added', () => {
		it('should have the role="dialog" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[role="dialog"]')).to.have.length(1);
		});

		it('should have the aria-modal="true" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[aria-modal="true"]')).to.have.length(1);
		});

		it('should have the aria-hidden="true" attribute', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail[aria-hidden="true"]')).to.have.length(1);
		});

		it('should have the tabindex attribute on the close button', () => {
			tableDetailComponent.init($body);

			expect($body.find('.table-detail__header-close[tabindex="-1"]')).to.have.length(1);
		});
	});

	describe('When the view panel link is clicked', () => {
		it('should prevent the default behaviour of the click', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect(clickEvent.isDefaultPrevented()).to.be.true;
		});

		it('should set a custom panel title if one is set', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-title]').text()).to.equal('custom panel title');
		});

		it('should empty the panel body and replace the content', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-panel-body]').append('some content to be removed');

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body]').html()).to.equal('
content
<form><button>button</button></form>');
		});

		it('should add the "in" class to the backdrop to show it', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.true;
		});

		it('should add the "table-detail--open" class to the panel to open it', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.true;
		});

		it('should focus the close button if there is no other focusable element in the panel', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-content]').attr('data-table-detail-content', '
Content
')

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-close-panel]').is(':focus')).to.be.true;
		});

		it('should focus the first focusable element if one is present ', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] form button').is(':focus')).to.be.true;
		});
	});

	describe('When the view panel link is clicked from the child row', () => {
		it('should fetch the panel title from the parent row', () => {
			tableDetailComponent.init($body);

			$body.find('.child [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-title]').text()).to.equal('custom panel title');
		});

		it('should empty the panel body and replace the content', () => {
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-panel-body]').append('some content to be removed');

			$body.find('.child [data-table-detail-view-detail]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body]').html()).to.equal('
content
<form><button>button</button></form>');
		});
	});

	describe('when the panel is open and tab is pressed', () => {
		beforeEach(() => {
			tabKeyDownEvent.keyCode = 9;
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-view-detail="true"]').trigger(clickEvent);
		});

		it('should focus the first element, when the last element was previously focused', () => {
			$body.find('.table-detail--open .table-detail__body form button').focus();

			$html.trigger(tabKeyDownEvent);

			expect($body.find('.table-detail--open .table-detail__header-close').is(':focus')).to.be.true;
		});
	});

	describe('when the panel is open and shift + tab is pressed', () => {
		beforeEach(() => {
			tabKeyDownEvent.keyCode = 9;
			tabKeyDownEvent.shiftKey = true;
			tableDetailComponent.init($body);
			$body.find('[data-table-detail-view-detail="true"]').trigger(clickEvent);
		});

		it('should focus the last element, when the first element was previously focused', () => {
			$body.find('.table-detail--open .table-detail__header-close').focus();

			$html.trigger(tabKeyDownEvent);

			expect($body.find('.table-detail--open .table-detail__body form button').is(':focus')).to.be.true;
		});
	});

	describe('When the close panel button is clicked', () => {
		it('should remove the "in" class from the backdrop to hide it', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('should remove the "table-detail--open" class from the panel', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});

		it('should add tabindex="-1" to all focusable elements', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] button').attr('tabindex')).to.equal('-1');
			expect($body.find('[data-table-detail-close-panel]').attr('tabindex')).to.equal('-1');
		});
	});

	describe('When the panel is opened and closed', () => {
		it('should not be possible to focus elements in the panel', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('[data-table-detail-panel-body] button').attr('tabindex')).to.equal('-1');
			expect($body.find('[data-table-detail-close-panel]').attr('tabindex')).to.equal('-1');
		});

		it('should add the aria-hidden="true" attribute to the panel', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			$body.find('[data-table-detail-close-panel]').trigger(clickEvent);

			expect($body.find('.table-detail[aria-hidden="true"]')).to.have.length(1);
		});
	});

	describe('When the ESC key is pressed', () => {
		beforeEach(() => {
			keyDownEvent.keyCode = 27;
			tableDetailComponent.init($body);
			$body.find('table [data-table-detail-view-detail="true"]').trigger(clickEvent);
			$html.trigger(keyDownEvent);
		});

		it('should remove the "in" class from the backdrop to hide it', () => {
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('remove the "table-detail--open" class to the panel to close it', () => {
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});
	});

	describe('When the backdrop overlay is clicked', () => {
		it('should remove the "in" class from the backdrop to hide it', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.true;

			$body.find('.table-detail-backdrop').trigger(clickEvent);
			expect($body.find('.table-detail-backdrop').hasClass('in')).to.be.false;
		});

		it('should remove the "table-detail--open" class from the panel to close it', () => {
			tableDetailComponent.init($body);

			$body.find('.parent [data-table-detail-view-detail]').trigger(clickEvent);
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.true;

			$body.find('.table-detail-backdrop').trigger(clickEvent);
			expect($body.find('[data-table-detail-panel]').hasClass('table-detail--open')).to.be.false;
		});
	});
});
<|endoftext|>


<commit_before>import React, { lazy } from "react";

const Gallery = lazy(() => import("./pages/event/gallery"));
const Legends = lazy(() => import("./pages/event/legends"));
const LegendId = lazy(() => import("./pages/event/legend/id"));
const Rules = lazy(() => import("./pages/event/rules"));
const Info = lazy(() => import("./pages/event/info"));
const Contacts = lazy(() => import("./pages/event/contacts"));
const Races = lazy(() => import("./pages/event/races"));
const RaceId = lazy(() => import("./pages/event/race/id"));
const RegistrationNew = lazy(() => import("./pages/event/signup"));
const Attendees = lazy(() => import("./pages/event/attendees"));
const Confirmation = lazy(() => import("./pages/event/confirmation"));

export const useEventRouter = (event) => {
  const tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);

  return [
    {
      type: "visible",
      title: "Legendy a příběhy",
      icon: "receipt",
      path: `/${event.id}/legends`,
      owns: [`/${event.id}/legend/`],
      component: Legends,
    },
    {
      type: "hidden",
      path: `/${event.id}/legend/:id`,
      component: LegendId,
    },
    {
      type: "visible",
      title: "Pravidla",
      icon: "gavel",
      path: `/${event.id}/rules`,
      component: Rules,
    },
    {
      type: "visible",
      title: "Svět",
      icon: "map",
    },
    {
      type: "visible",
      title: "Bojující strany",
      icon: "group",
      path: `/${event.id}/races`,
      owns: [`/${event.id}/race/`],
      component: Races,
    },
    {
      path: `/${event.id}/race/:id`,
      component: RaceId,
    },
    {
      type: "visible",
      title: "Důležité informace",
      icon: "location_on",
      path: `/${event.id}/info`,
      component: Info,
    },
    {
      type: "visible",
      title: "Kontakty",
      icon: "mail_outline",
      path: `/${event.id}/contacts`,
      component: Contacts,
    },
    {
      type: "visible",
      title: "Galerie",
      className: "material-icons-outlined",
      icon: "collections_outline",
      path: `/${event.id}/gallery`,
      disabled: event.date.toDate() > tomorrow,
      component: Gallery,
    },
    {
      type: "divider",
    },
    {
      type: "visible",
      title: "Nová registrace",
      icon: "person_add",
      path: `/${event.id}/signup`,
      disabled:
        !event.registrationAvailable && process.env.NODE_ENV !== "development",
      component: RegistrationNew,
    },
    {
      type: "visible",
      title: "Účastníci",
      icon: "how_to_reg",
      path: `/${event.id}/attendees`,
      disabled: event.date.toDate() < tomorrow,
      component: Attendees,
    },
    {
      path: `/${event.id}/confirmation`,
      component: Confirmation,
    },
  ];
};
<commit_msg>fix: time based routes before/after event<commit_after>import React, { lazy } from "react";

const Gallery = lazy(() => import("./pages/event/gallery"));
const Legends = lazy(() => import("./pages/event/legends"));
const LegendId = lazy(() => import("./pages/event/legend/id"));
const Rules = lazy(() => import("./pages/event/rules"));
const Info = lazy(() => import("./pages/event/info"));
const Contacts = lazy(() => import("./pages/event/contacts"));
const Races = lazy(() => import("./pages/event/races"));
const RaceId = lazy(() => import("./pages/event/race/id"));
const RegistrationNew = lazy(() => import("./pages/event/signup"));
const Attendees = lazy(() => import("./pages/event/attendees"));
const Confirmation = lazy(() => import("./pages/event/confirmation"));

export const useEventRouter = (event) => {
  const tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  tomorrow.setUTCHours(23);
  tomorrow.setUTCMinutes(59);
  const eventInFuture = Number(event.date.toDate()) < Number(tomorrow);

  return [
    {
      type: "visible",
      title: "Legendy a příběhy",
      icon: "receipt",
      path: `/${event.id}/legends`,
      owns: [`/${event.id}/legend/`],
      component: Legends,
    },
    {
      type: "hidden",
      path: `/${event.id}/legend/:id`,
      component: LegendId,
    },
    {
      type: "visible",
      title: "Pravidla",
      icon: "gavel",
      path: `/${event.id}/rules`,
      component: Rules,
    },
    {
      type: "visible",
      title: "Svět",
      icon: "map",
    },
    {
      type: "visible",
      title: "Bojující strany",
      icon: "group",
      path: `/${event.id}/races`,
      owns: [`/${event.id}/race/`],
      component: Races,
    },
    {
      path: `/${event.id}/race/:id`,
      component: RaceId,
    },
    {
      type: "visible",
      title: "Důležité informace",
      icon: "location_on",
      path: `/${event.id}/info`,
      component: Info,
    },
    {
      type: "visible",
      title: "Kontakty",
      icon: "mail_outline",
      path: `/${event.id}/contacts`,
      component: Contacts,
    },
    {
      type: "visible",
      title: "Galerie",
      className: "material-icons-outlined",
      icon: "collections_outline",
      path: `/${event.id}/gallery`,
      disabled: eventInFuture,
      component: Gallery,
    },
    {
      type: "divider",
    },
    {
      type: "visible",
      title: "Nová registrace",
      icon: "person_add",
      path: `/${event.id}/signup`,
      disabled:
        (!event.registrationAvailable || eventInFuture) &&
        process.env.NODE_ENV !== "development",
      component: RegistrationNew,
    },
    {
      type: "visible",
      title: "Účastníci",
      icon: "how_to_reg",
      path: `/${event.id}/attendees`,
      disabled: !eventInFuture,
      component: Attendees,
    },
    {
      path: `/${event.id}/confirmation`,
      component: Confirmation,
    },
  ];
};

1636203480000;
1636243164621;
<|endoftext|>


<commit_before>const GOOGLE = new plugin.google.maps.LatLng(37.422858, -122.085065);
const GOOGLE_TOKYO = new plugin.google.maps.LatLng(35.660556,139.729167);
const GOOGLE_SYDNEY = new plugin.google.maps.LatLng(-33.867487,151.20699);
const STATUE_OF_LIBERTY = new plugin.google.maps.LatLng(40.689249,-74.0445);
const HND_AIR_PORT = new plugin.google.maps.LatLng(35.548852,139.784086);
const SFO_AIR_PORT = new plugin.google.maps.LatLng(37.615223,-122.389979);
const GORYOKAKU_JAPAN = new plugin.google.maps.LatLng(41.796875,140.757007);
const GORYOKAKU_POINTS = [
  new plugin.google.maps.LatLng(41.79883, 140.75675),
  new plugin.google.maps.LatLng(41.799240000000005, 140.75875000000002),
  new plugin.google.maps.LatLng(41.797650000000004, 140.75905),
  new plugin.google.maps.LatLng(41.79637, 140.76018000000002),
  new plugin.google.maps.LatLng(41.79567, 140.75845),
  new plugin.google.maps.LatLng(41.794470000000004, 140.75714000000002),
  new plugin.google.maps.LatLng(41.795010000000005, 140.75611),
  new plugin.google.maps.LatLng(41.79477000000001, 140.75484),
  new plugin.google.maps.LatLng(41.79576, 140.75475),
  new plugin.google.maps.LatLng(41.796150000000004, 140.75364000000002),
  new plugin.google.maps.LatLng(41.79744, 140.75454000000002),
  new plugin.google.maps.LatLng(41.79909000000001, 140.75465),
  new plugin.google.maps.LatLng(41.79883, 140.75673)
];
var map,
    mTileOverlay;

window.onerror = function(message, file, line) {
  var error = [];
  error.push('---[error]');
  if (typeof message == "object") {
    var keys = Object.keys(message);
    keys.forEach(function(key) {
      error.push('[' + key + '] ' + message[key]);
    });
  } else {
    error.push(line + ' at ' + file);
    error.push(message);
  }
  alert(error.join("\n"));
};
document.addEventListener('deviceready', function() {

  var i,
      buttons = document.getElementsByTagName("button");
  for (i = 0; i < buttons.length; i++) {
    if (buttons[i].getAttribute("name") != "initMap") {
      buttons[i].disabled = 'disabled';
    }
  }
}, false);

function getMap1() {
  map = plugin.google.maps.Map.getMap();
  map.addEventListener('map_ready', onMapReady);
}
function getMap2() {
  map = plugin.google.maps.Map.getMap({
    'mapType': plugin.google.maps.MapTypeId.HYBRID,
    'controls': {
      'compass': true,
      'myLocationButton': true,
      'indoorPicker': true,
      'zoom': true
    },
    'gestures': {
      'scroll': true,
      'tilt': true,
      'rotate': true
    },
    'camera': {
      'latLng': GORYOKAKU_JAPAN,
      'tilt': 30,
      'zoom': 16,
      'bearing': 50
    }
  });
  map.addEventListener('map_ready', onMapReady);
}
function onMapReady() {
  var i,
      buttons = document.getElementsByTagName("button");
  for (i = 0; i < buttons.length; i++) {
    if (buttons[i].getAttribute("name") != "initMap") {
      buttons[i].disabled = undefined;
    } else {
      buttons[i].disabled = "disabled";
    }
  }

  var evtName = plugin.google.maps.event.MAP_LONG_CLICK;
  map.on(evtName, function(latLng) {
    alert("Map was long clicked.\n" +
          latLng.toUrlValue());
  });
  map.showDialog();
}

function showMap() {
  map.showDialog();
}

function setMapTypeId() {
  var select = document.getElementById('mapTypeSelect');
  var mapType = (plugin.google.maps.MapTypeId[select.value]);
  map.setMapTypeId(mapType);
  map.showDialog();
}

function animateCamera() {
  map.showDialog();
  map.animateCamera({
    'target': GOOGLE,
    'tilt': 60,
    'zoom': 18,
    'bearing': 140
  });
}

function animateCamera_delay() {
  map.showDialog();
  map.animateCamera({
    'target': GOOGLE,
    'tilt': 60,
    'zoom': 18,
    'bearing': 140
  }, 5000);
}

function moveCamera() {
  map.moveCamera({
    'target': GORYOKAKU_JAPAN,
    'zoom': 16,
    'tilt': 30
  }, function() {
    var mapType = plugin.google.maps.MapTypeId.HYBRID;
    map.setMapTypeId(mapType);
    map.showDialog();
  });
}

function getCameraPosition() {
  map.getCameraPosition(function(camera) {
    var buff = ["Current camera position:\n",
                "latitude:" + camera.target.lat,
                "longitude:" + camera.target.lng,
                "zoom:" + camera.zoom,
                "tilt:" + camera.tilt,
                "bearing:" + camera.bearing].join("\n");
    alert(buff);
  });
}

function getMyLocation() {

  map.getMyLocation(function(location) {
    var msg = ["Current your location:\n",
      "latitude:" + location.latLng.lat,
      "longitude:" + location.latLng.lng,
      "speed:" + location.speed,
      "time:" + location.time,
      "bearing:" + location.bearing].join("\n");

    map.moveCamera({
      'target': location.latLng
    });

    map.addMarker({
      'position': location.latLng,
      'title': msg
    }, function(marker) {
      marker.showInfoWindow();
      map.showDialog();
    });

  });
}

function addMarker1() {
  map.showDialog();
  map.moveCamera({
    'target': GOOGLE,
    'zoom': 17
  });
  map.addMarker({
    'position': GOOGLE,
    'title': ["Hello GoogleMap", "for", "Cordova!"].join("\n")
  }, function(marker) {
    marker.showInfoWindow();
  });
}

function addMarker2() {
  map.moveCamera({
    'target': STATUE_OF_LIBERTY,
    'zoom': 16
  });
  map.showDialog();
  map.addMarker({
    'position': STATUE_OF_LIBERTY,
    'title': "Statue of Liberty"
  }, function(marker) {
    marker.showInfoWindow();
  });
}

function addMarker3() {
  map.showDialog();
  map.addMarker({
    'position': GOOGLE_TOKYO,
    'title': 'Google Tokyo!',
    'icon': {
      'url': 'www/images/google_tokyo_icon.png',
      'size': {
        'width': 37,
        'height': 63
      }
     }
  }, function(marker) {
    map.animateCamera({
      'target': GOOGLE_TOKYO,
      'tilt': 60,
      'zoom': 14,
      'bearing': 0
    }, function() {
      marker.showInfoWindow();
    });
  });
}

function addMarker4() {
  map.showDialog();
  map.moveCamera({
    'target': GOOGLE_SYDNEY,
    'zoom': 16
  });
  map.addMarker({
    'position': GOOGLE_SYDNEY,
    'title': "Google Sydney",
    'snippet': "click, then remove",
    'draggable': true,
    'markerClick': function(marker) {
      marker.showInfoWindow();
    },
    'infoClick': function(marker) {
      marker.remove();
    }
  });
}

function addPolyline() {
  map.showDialog();

  map.addPolyline({
    points: [
      HND_AIR_PORT,
      SFO_AIR_PORT
    ],
    'color' : '#AA00FF',
    'width': 10,
    'geodesic': true
  }, function(polyline) {

    map.animateCamera({
      'target': polyline.getPoints(),
      'zoom': 2
    });
  });
}

function addPolygon() {
  map.showDialog();

  map.addPolygon({
    points: GORYOKAKU_POINTS,
    'strokeColor' : '#AA00FF',
    'strokeWidth': 5,
    'fillColor' : '#880000'
  }, function(polygon) {

    map.animateCamera({
      'target': polygon.getPoints()
    });
  });
}

function addCircle() {
  map.showDialog();

  map.addCircle({
    'center': GOOGLE,
    'radius': 300,
    'strokeColor' : '#AA00FF',
    'strokeWidth': 5,
    'fillColor' : '#880000'
  });

  map.animateCamera({
    'target': GOOGLE,
    'zoom': 14
  });
}

function addGroundOverlay() {
  var bounds = [
    new plugin.google.maps.LatLng(40.712216,-74.22655),
    new plugin.google.maps.LatLng(40.773941,-74.12544)
  ];

  map.addGroundOverlay({
    'url': "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
    'bounds': bounds,
    'opacity': 0.5
  }, function(groundOverlay) {
    map.showDialog();
    map.animateCamera({
      'target': bounds
    });
  });
}

function addTileOverlay() {
  map.addTileOverlay({
    // <x>,<y>,<zoom> are replaced with values
    tileUrlFormat: "http://tile.stamen.com/watercolor/<zoom>/<x>/<y>.jpg"
  }, function(tileOverlay) {
    mTileOverlay = tileOverlay;
    map.showDialog();
  });
}

function geocoding() {
  var input = document.getElementById("geocoder_input");
  var request = {
    'address': input.value
  };
  map.geocode(request, function(results) {
    if (results.length) {
      map.showDialog();
      var result = results[0];
      var position = result.position;

      map.addMarker({
        'position': position,
        'title':  JSON.stringify(result.position)
      }, function(marker) {

        map.animateCamera({
          'target': position,
          'zoom': 17
        }, function() {
          marker.showInfoWindow();
        });

      });
    } else {
      alert("Not found");
    }
  });
}

function reverseGeocoding() {
  var request = {
    'position': new plugin.google.maps.LatLng(37.820905,-122.478576)
  };
  map.geocode(request, function(results) {
    if (results.length) {
      map.showDialog();

      var mapType = plugin.google.maps.MapTypeId.HYBRID;
      map.setMapTypeId(mapType);

      var result = results[0];
      var position = result.position;

      map.addMarker({
        'position': position,
        'title':  result.thoroughfare
      }, function(marker) {

        map.animateCamera({
          'target': position,
          'zoom': 15
        }, function() {
          marker.showInfoWindow();
        });

      });
    } else {
      alert("Not found");
    }
  });
}
<commit_msg>Fix example code<commit_after>const GOOGLE = new plugin.google.maps.LatLng(37.422858, -122.085065);
const GOOGLE_TOKYO = new plugin.google.maps.LatLng(35.660556,139.729167);
const GOOGLE_SYDNEY = new plugin.google.maps.LatLng(-33.867487,151.20699);
const STATUE_OF_LIBERTY = new plugin.google.maps.LatLng(40.689249,-74.0445);
const HND_AIR_PORT = new plugin.google.maps.LatLng(35.548852,139.784086);
const SFO_AIR_PORT = new plugin.google.maps.LatLng(37.615223,-122.389979);
const GORYOKAKU_JAPAN = new plugin.google.maps.LatLng(41.796875,140.757007);
const GORYOKAKU_POINTS = [
  new plugin.google.maps.LatLng(41.79883, 140.75675),
  new plugin.google.maps.LatLng(41.799240000000005, 140.75875000000002),
  new plugin.google.maps.LatLng(41.797650000000004, 140.75905),
  new plugin.google.maps.LatLng(41.79637, 140.76018000000002),
  new plugin.google.maps.LatLng(41.79567, 140.75845),
  new plugin.google.maps.LatLng(41.794470000000004, 140.75714000000002),
  new plugin.google.maps.LatLng(41.795010000000005, 140.75611),
  new plugin.google.maps.LatLng(41.79477000000001, 140.75484),
  new plugin.google.maps.LatLng(41.79576, 140.75475),
  new plugin.google.maps.LatLng(41.796150000000004, 140.75364000000002),
  new plugin.google.maps.LatLng(41.79744, 140.75454000000002),
  new plugin.google.maps.LatLng(41.79909000000001, 140.75465),
  new plugin.google.maps.LatLng(41.79883, 140.75673)
];
var map,
    mTileOverlay;

window.onerror = function(message, file, line) {
  var error = [];
  error.push('---[error]');
  if (typeof message == "object") {
    var keys = Object.keys(message);
    keys.forEach(function(key) {
      error.push('[' + key + '] ' + message[key]);
    });
  } else {
    error.push(line + ' at ' + file);
    error.push(message);
  }
  alert(error.join("\n"));
};
document.addEventListener('deviceready', function() {

  var i,
      buttons = document.getElementsByTagName("button");
  for (i = 0; i < buttons.length; i++) {
    if (buttons[i].getAttribute("name") != "initMap") {
      buttons[i].disabled = 'disabled';
    }
  }
}, false);

function getMap1() {
  map = plugin.google.maps.Map.getMap();
  map.addEventListener('map_ready', onMapReady);
}
function getMap2() {
  map = plugin.google.maps.Map.getMap({
    'mapType': plugin.google.maps.MapTypeId.HYBRID,
    'controls': {
      'compass': true,
      'myLocationButton': true,
      'indoorPicker': true,
      'zoom': true
    },
    'gestures': {
      'scroll': true,
      'tilt': true,
      'rotate': true
    },
    'camera': {
      'latLng': GORYOKAKU_JAPAN,
      'tilt': 30,
      'zoom': 16,
      'bearing': 50
    }
  });
  map.addEventListener('map_ready', onMapReady);
}
function onMapReady() {
  var i,
      buttons = document.getElementsByTagName("button");
  for (i = 0; i < buttons.length; i++) {
    if (buttons[i].getAttribute("name") != "initMap") {
      buttons[i].disabled = undefined;
    } else {
      buttons[i].disabled = "disabled";
    }
  }

  var evtName = plugin.google.maps.event.MAP_LONG_CLICK;
  map.on(evtName, function(latLng) {
    alert("Map was long clicked.\n" +
          latLng.toUrlValue());
  });
  map.showDialog();
}

function showMap() {
  map.showDialog();
}

function setMapTypeId() {
  var select = document.getElementById('mapTypeSelect');
  var mapType = (plugin.google.maps.MapTypeId[select.value]);
  map.setMapTypeId(mapType);
  map.showDialog();
}

function animateCamera() {
  map.showDialog();
  map.animateCamera({
    'target': GOOGLE,
    'tilt': 60,
    'zoom': 18,
    'bearing': 140
  });
}

function animateCamera_delay() {
  map.showDialog();
  map.animateCamera({
    'target': GOOGLE,
    'tilt': 60,
    'zoom': 18,
    'bearing': 140
  }, 5000);
}

function moveCamera() {
  map.moveCamera({
    'target': STATUE_OF_LIBERTY,
    'zoom': 17,
    'tilt': 30
  }, function() {
    var mapType = plugin.google.maps.MapTypeId.HYBRID;
    map.setMapTypeId(mapType);
    map.showDialog();
  });
}

function getCameraPosition() {
  map.getCameraPosition(function(camera) {
    var buff = ["Current camera position:\n",
                "latitude:" + camera.target.lat,
                "longitude:" + camera.target.lng,
                "zoom:" + camera.zoom,
                "tilt:" + camera.tilt,
                "bearing:" + camera.bearing].join("\n");
    alert(buff);
  });
}

function getMyLocation() {

  map.getMyLocation(function(location) {
    var msg = ["Current your location:\n",
      "latitude:" + location.latLng.lat,
      "longitude:" + location.latLng.lng,
      "speed:" + location.speed,
      "time:" + location.time,
      "bearing:" + location.bearing].join("\n");

    map.moveCamera({
      'target': location.latLng
    });

    map.addMarker({
      'position': location.latLng,
      'title': msg
    }, function(marker) {
      marker.showInfoWindow();
      map.showDialog();
    });

  });
}

function addMarker1() {
  map.showDialog();
  map.moveCamera({
    'target': GOOGLE,
    'zoom': 17
  });
  map.addMarker({
    'position': GOOGLE,
    'title': ["Hello GoogleMap", "for", "Cordova!"].join("\n")
  }, function(marker) {
    marker.showInfoWindow();
  });
}

function addMarker2() {
  map.moveCamera({
    'target': STATUE_OF_LIBERTY,
    'zoom': 16
  });
  map.showDialog();
  map.addMarker({
    'position': STATUE_OF_LIBERTY,
    'title': "Statue of Liberty"
  }, function(marker) {
    marker.showInfoWindow();
  });
}

function addMarker3() {
  map.showDialog();
  map.addMarker({
    'position': GOOGLE_TOKYO,
    'title': 'Google Tokyo!',
    'icon': {
      'url': 'www/images/google_tokyo_icon.png',
      'size': {
        'width': 37,
        'height': 63
      }
     }
  }, function(marker) {
    map.animateCamera({
      'target': GOOGLE_TOKYO,
      'tilt': 60,
      'zoom': 14,
      'bearing': 0
    }, function() {
      marker.showInfoWindow();
    });
  });
}

function addMarker4() {
  map.showDialog();
  map.moveCamera({
    'target': GOOGLE_SYDNEY,
    'zoom': 16
  });
  map.addMarker({
    'position': GOOGLE_SYDNEY,
    'title': "Google Sydney",
    'snippet': "click, then remove",
    'draggable': true,
    'markerClick': function(marker) {
      marker.showInfoWindow();
    },
    'infoClick': function(marker) {
      marker.remove();
    }
  });
}

function addPolyline() {
  map.showDialog();

  map.addPolyline({
    points: [
      HND_AIR_PORT,
      SFO_AIR_PORT
    ],
    'color' : '#AA00FF',
    'width': 10,
    'geodesic': true
  }, function(polyline) {

    map.animateCamera({
      'target': polyline.getPoints(),
      'zoom': 2
    });
  });
}

function addPolygon() {
  map.showDialog();

  map.addPolygon({
    points: GORYOKAKU_POINTS,
    'strokeColor' : '#AA00FF',
    'strokeWidth': 5,
    'fillColor' : '#880000'
  }, function(polygon) {

    map.animateCamera({
      'target': polygon.getPoints()
    });
  });
}

function addCircle() {
  map.showDialog();

  map.addCircle({
    'center': GOOGLE,
    'radius': 300,
    'strokeColor' : '#AA00FF',
    'strokeWidth': 5,
    'fillColor' : '#880000'
  });

  map.animateCamera({
    'target': GOOGLE,
    'zoom': 14
  });
}

function addGroundOverlay() {
  var bounds = [
    new plugin.google.maps.LatLng(40.712216,-74.22655),
    new plugin.google.maps.LatLng(40.773941,-74.12544)
  ];

  map.addGroundOverlay({
    'url': "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
    'bounds': bounds,
    'opacity': 0.5
  }, function(groundOverlay) {
    map.showDialog();
    map.animateCamera({
      'target': bounds
    });
  });
}

function addTileOverlay() {
  map.addTileOverlay({
    // <x>,<y>,<zoom> are replaced with values
    tileUrlFormat: "http://tile.stamen.com/watercolor/<zoom>/<x>/<y>.jpg"
  }, function(tileOverlay) {
    mTileOverlay = tileOverlay;
    map.showDialog();
  });
}

function geocoding() {
  var input = document.getElementById("geocoder_input");
  var request = {
    'address': input.value
  };
  map.geocode(request, function(results) {
    if (results.length) {
      map.showDialog();
      var result = results[0];
      var position = result.position;

      map.addMarker({
        'position': position,
        'title':  JSON.stringify(result.position)
      }, function(marker) {

        map.animateCamera({
          'target': position,
          'zoom': 17
        }, function() {
          marker.showInfoWindow();
        });

      });
    } else {
      alert("Not found");
    }
  });
}

function reverseGeocoding() {
  var request = {
    'position': new plugin.google.maps.LatLng(37.820905,-122.478576)
  };
  map.geocode(request, function(results) {
    if (results.length) {
      map.showDialog();

      var mapType = plugin.google.maps.MapTypeId.HYBRID;
      map.setMapTypeId(mapType);

      var result = results[0];
      var position = result.position;

      map.addMarker({
        'position': position,
        'title':  result.thoroughfare
      }, function(marker) {

        map.animateCamera({
          'target': position,
          'zoom': 15
        }, function() {
          marker.showInfoWindow();
        });

      });
    } else {
      alert("Not found");
    }
  });
}
<|endoftext|>


<commit_before>import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import Ember from 'ember';
import sinon from 'sinon';
import RButtonMixin from 'ui-library/mixins/r-button-mixin';

const { get } = Ember;

describe('Unit | Mixin | r-button-mixin', function() {
  let subject;

  beforeEach(function () {
    const RButtonMixinObject = Ember.Object.extend(RButtonMixin, {
      _super: sinon.spy()
    });

    subject = RButtonMixinObject.create();
  });

  describe('properties', function () {
    it('should have correct classNames set', function () {
      expect(get(subject, 'classNames')).to.be.eql(['r-btn']);
    });

    it('should have correct classNameBindings set', function () {
      expect(get(subject, 'classNameBindings')).to.be.eql([
        // types
        'primary:r-btn-primary',
        'secondary:r-btn-secondary',
        'cancel:r-btn-cancel',

        // states
        'loading:r-btn-loading',

        // sizes
        'big:r-btn-large',
        'small:r-btn-small'
      ]);
    });

    it('should have correct attributes set', function () {
      expect(get(subject, 'attributes')).to.be.eql({
        variant: ['primary', 'secondary', 'cancel'],
        size: ['small', 'big']
      });
    });

    it('should have correct defaults set', function () {
      expect(get(subject, 'defaults')).to.be.eql({
        variant: 'secondary',
        size: 'small'
      });
    });
  });

  // describe('methods', function () {
  //   describe('init', function () {
  //     const method = this.title;
  //
  //     it('should call _setOptionFlag for each key in options property', function () {
  //       set(subject, '_setOptionFlag', sinon.spy());
  //
  //       subject[method]();
  //
  //       Object.keys(get(subject, 'options')).forEach(key => {
  //         expect(get(subject, '_setOptionFlag').calledWith(key)).to.be.equal(true);
  //       });
  //     });
  //   });
  //
  //   describe('_setOptionFlag', function () {
  //     const method = this.title;
  //     const flagType = 'size';
  //     const flagName = 'big';
  //
  //     it('should set given flagName', function () {
  //       subject.setProperties({
  //         _isValidFlagName: sinon.stub().returns(true),
  //         [flagType]: flagName
  //       });
  //
  //       subject[method](flagType);
  //
  //       expect(get(subject, flagName)).to.be.equal(true);
  //     });
  //
  //     it('should set default flagName', function () {
  //       subject.setProperties({
  //         _isValidFlagName: sinon.stub().returns(false),
  //         [flagType]: flagName
  //       });
  //
  //       subject[method](flagType);
  //
  //       expect(get(subject, get(subject, `defaults.${flagType}`))).to.be.equal(true);
  //     })
  //   });
  //
  //   describe('_isValidFlagName', function () {
  //     const method = this.title;
  //
  //     it('should return true', function () {
  //       expect(subject[method]('size', 'big')).to.be.equal(true);
  //     });
  //
  //     it('should return false', function () {
  //       expect(subject[method]('size', 'foo-bar')).to.be.equal(false);
  //     });
  //   });
  // });
});
<commit_msg>Fix failing test<commit_after>import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import Ember from 'ember';
import sinon from 'sinon';
import RButtonMixin from 'ui-library/mixins/r-button-mixin';

const { get } = Ember;

describe('Unit | Mixin | r-button-mixin', function() {
  let subject;

  beforeEach(function () {
    const RButtonMixinObject = Ember.Object.extend(RButtonMixin, {
      _super: sinon.spy()
    });

    subject = RButtonMixinObject.create();
  });

  describe('properties', function () {
    it('should have correct classNames set', function () {
      expect(get(subject, 'classNames')).to.be.eql(['r-btn']);
    });

    it('should have correct classNameBindings set', function () {
      expect(get(subject, 'classNameBindings')).to.be.eql([
        // types
        'primary:r-btn-primary',
        'secondary:r-btn-secondary',
        'cancel:r-btn-cancel',

        // states
        'loading:r-btn-loading',

        // sizes
        'big:r-btn-large',
        'small:r-btn-small'
      ]);
    });

    it('should have correct attributes set', function () {
      expect(get(subject, 'allowedAttributes')).to.be.eql({
        variant: ['primary', 'secondary', 'cancel'],
        size: ['small', 'big']
      });
    });

    it('should have correct defaults set', function () {
      expect(get(subject, 'defaults')).to.be.eql({
        variant: 'secondary',
        size: 'small'
      });
    });
  });

  // describe('methods', function () {
  //   describe('init', function () {
  //     const method = this.title;
  //
  //     it('should call _setOptionFlag for each key in options property', function () {
  //       set(subject, '_setOptionFlag', sinon.spy());
  //
  //       subject[method]();
  //
  //       Object.keys(get(subject, 'options')).forEach(key => {
  //         expect(get(subject, '_setOptionFlag').calledWith(key)).to.be.equal(true);
  //       });
  //     });
  //   });
  //
  //   describe('_setOptionFlag', function () {
  //     const method = this.title;
  //     const flagType = 'size';
  //     const flagName = 'big';
  //
  //     it('should set given flagName', function () {
  //       subject.setProperties({
  //         _isValidFlagName: sinon.stub().returns(true),
  //         [flagType]: flagName
  //       });
  //
  //       subject[method](flagType);
  //
  //       expect(get(subject, flagName)).to.be.equal(true);
  //     });
  //
  //     it('should set default flagName', function () {
  //       subject.setProperties({
  //         _isValidFlagName: sinon.stub().returns(false),
  //         [flagType]: flagName
  //       });
  //
  //       subject[method](flagType);
  //
  //       expect(get(subject, get(subject, `defaults.${flagType}`))).to.be.equal(true);
  //     })
  //   });
  //
  //   describe('_isValidFlagName', function () {
  //     const method = this.title;
  //
  //     it('should return true', function () {
  //       expect(subject[method]('size', 'big')).to.be.equal(true);
  //     });
  //
  //     it('should return false', function () {
  //       expect(subject[method]('size', 'foo-bar')).to.be.equal(false);
  //     });
  //   });
  // });
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import mixinUnderTest from 'sl-ember-components/mixins/sl-input-based';;

module( 'Unit | Mixin | sl input based' );

test( 'Successfully mixed', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create();

    assert.ok( subject );
});

test( 'Disabled, optional, readonly, and required are false by default', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create();

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Disabled is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        disabled: true
    });

    assert.strictEqual(
        subject.get( 'disabled' ),
        true,
        'Disabled was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Optional is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        optional: true
    });

    assert.strictEqual(
        subject.get( 'optional' ),
        true,
        'Optional was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Readonly is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        readonly: true
    });

    assert.strictEqual(
        subject.get( 'readonly' ),
        true,
        'Readonly was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Required is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        required: true
    });

    assert.strictEqual(
        subject.get( 'required' ),
        true,
        'Required was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );
});

test( 'All parameters can be passed', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        disabled: true,
        optional: true,
        readonly: true,
        required: true
    });

    assert.strictEqual(
        subject.get( 'disabled' ),
        true,
        'Disabled was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        true,
        'Optional was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        true,
        'Readonly was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        true,
        'Required was properly passed as a parameter'
    );
});
<commit_msg>#240 remove extra semicolon<commit_after>import Ember from 'ember';
import mixinUnderTest from 'sl-ember-components/mixins/sl-input-based';

module( 'Unit | Mixin | sl input based' );

test( 'Successfully mixed', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create();

    assert.ok( subject );
});

test( 'Disabled, optional, readonly, and required are false by default', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create();

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Disabled is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        disabled: true
    });

    assert.strictEqual(
        subject.get( 'disabled' ),
        true,
        'Disabled was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Optional is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        optional: true
    });

    assert.strictEqual(
        subject.get( 'optional' ),
        true,
        'Optional was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Readonly is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        readonly: true
    });

    assert.strictEqual(
        subject.get( 'readonly' ),
        true,
        'Readonly was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        false,
        'Required is false by default'
    );
});

test( 'Required is passed as a parameter', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        required: true
    });

    assert.strictEqual(
        subject.get( 'required' ),
        true,
        'Required was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'disabled' ),
        false,
        'Disabled is false by default'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        false,
        'Optional is false by default'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        false,
        'Readonly is false by default'
    );
});

test( 'All parameters can be passed', function( assert ) {
    let testObject = Ember.Object.extend( mixinUnderTest );
    let subject = testObject.create({
        disabled: true,
        optional: true,
        readonly: true,
        required: true
    });

    assert.strictEqual(
        subject.get( 'disabled' ),
        true,
        'Disabled was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'optional' ),
        true,
        'Optional was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'readonly' ),
        true,
        'Readonly was properly passed as a parameter'
    );

    assert.strictEqual(
        subject.get( 'required' ),
        true,
        'Required was properly passed as a parameter'
    );
});
<|endoftext|>


<commit_before>/*    Copyright 2019 Firewalla INC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict'

let instance = null;

const exec = require('child-process-promise').exec;
const fConfig = require('../../net2/config.js').getConfig();
const log = require('../../net2/logger.js')(__filename);

const sysManager = require('../../net2/SysManager.js');

const platformLoader = require('../../platform/PlatformLoader.js');
const platform = platformLoader.getPlatform();
const model = platform.getName();
const serial = platform.getBoardSerial();
const fs = require('fs');
const Promise = require('bluebird');

const f = require('../../net2/Firewalla.js');

Promise.promisifyAll(fs);

const rp = require('request-promise');

class FWDiag {
  constructor() {
    if(instance === null) {
      instance = this;
    }

    return instance;
  }

  getEndpoint() {
    return fConfig.firewallaDiagServerURL || `https://api.firewalla.com/diag/api/v1/device/`
  }

  async getGatewayMac(gatewayIP) {
    const pingCmd = `ping -q -c 1 -w 2 ${gatewayIP} || /bin/true`;
    await exec(pingCmd);

    const arpCmd = `arp -a -n | grep ${gatewayIP} -w | awk '{print $4}'`;
    const result = await exec(arpCmd);
    const mac = result.stdout;
    if(mac) {
      return mac.substring(0, 11);
    } else {
      return null;
    }
  }

  async getGatewayName(gatewayIP) {
    const cmd = `arp ${gatewayIP} | tail -n 1 | awk '{print $1}'`;
    // return empty if command execute failed
    const result = await exec(cmd).catch(() => "");
    const name = result.stdout;
    return name.replace(/\n$/, '')
  }

  async getBranchInfo() {
    const result = await exec("git rev-parse --abbrev-ref HEAD");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  getVersion() {
    return fConfig.version;
  }

  async getLongVersion() {
    const result = await exec("git describe --tags");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async getTotalMemory() {
    const result = await exec("free -m | awk '/Mem:/ {print $2}'");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async getGID() {
    const result = await exec("redis-cli hget sys:ept gid");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async hasLicenseFile() {
    const filePath = `${f.getHiddenFolder()}/license`;
    try {
      await fs.accessAsync(filePath, fs.constants.F_OK);
      return true;
    } catch (err) {
      return false;
    }
  }

  async prepareData(payload) {
    const inter = sysManager.getDefaultWanInterface()

    const ip = inter.ip_address;
    const gateway = inter.gateway_ip;
    const mac = inter.mac_address;

    const gatewayMac = await this.getGatewayMac(gateway);
    const gatewayName = await this.getGatewayName(gateway);

    const ts = Math.floor(new Date() / 1000);

    return Object.assign({}, payload, {
      gw: gateway,
      fw: ip,
      mac: mac,
      ts: ts,
      gw_mac: gatewayMac,
      gw_name: gatewayName,
      model: model
    });
  }

  async submitInfo(payload) {
    const data = await this.prepareData(payload);
    if(data.gw) {
      const rclient = require('../../util/redis_manager.js').getRedisClient();

      const options = {
        uri:  this.getEndpoint() + data.gw,
        method: 'POST',
        json: data
      }
      const result = await rp(options);
      if(result && result.mode) {
        await rclient.setAsync("recommend_firewalla_mode", result.mode);
      }

      if(result && result.guessedRouter) {
        await rclient.setAsync("guessed_router", JSON.stringify(result.guessedRouter));
      }

      log.info(`submitted ${payload.event} info to diag server successfully with result ${JSON.stringify(result)}`);
    }
  }

  async getCpuTemperature() {
    try {
      return platform.getCpuTemperature()
    } catch(err) {
      return -1;
    }
  }

  async prepareHelloData() {
    const inter = sysManager.getDefaultWanInterface()

    const firewallaIP = inter.ip_address;
    const mac = inter.mac_address;
    const gateway = inter.gateway_ip;

    const version = this.getVersion();

    const [gatewayMac, branch, longVersion, memory, gid, hasLicense, nicSpeed, cpuTemp] =
      await Promise.all([
        this.getGatewayMac(gateway),
        this.getBranchInfo(),
        this.getLongVersion(),
        this.getTotalMemory(),
        this.getGID(),
        this.hasLicenseFile(),
        platform.getNetworkSpeed(),
        this.getCpuTemperature()
      ]);

    return {
      mac,
      firewallaIP,
      gatewayMac,
      branch,
      version,
      longVersion,
      memory,
      model,
      serial,
      gid,
      hasLicense,
      nicSpeed,
      cpuTemp
    };
  }

  async sayHello() {
    const data = await this.prepareHelloData();
    const options = {
      uri: this.getEndpoint() + 'hello',
      method: 'POST',
      json: data
    }
    await rp(options);
    log.info("said hello to Firewalla Cloud");
  }

  async log(level, data) {
    const sysData = await this.prepareHelloData();
    const options = {
      uri: this.getEndpoint() + 'log/' + level,
      method: 'POST',
      json: Object.assign({}, data, sysData)
    }
    log.info(`Sending diag log, [${level}] ${JSON.stringify(data)}`);
    await rp(options);
  }
}

module.exports = new FWDiag();
<commit_msg>use signature mac instead of default wan<commit_after>/*    Copyright 2019 Firewalla INC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict'

let instance = null;

const exec = require('child-process-promise').exec;
const fConfig = require('../../net2/config.js').getConfig();
const log = require('../../net2/logger.js')(__filename);

const sysManager = require('../../net2/SysManager.js');

const platformLoader = require('../../platform/PlatformLoader.js');
const platform = platformLoader.getPlatform();
const model = platform.getName();
const serial = platform.getBoardSerial();
const fs = require('fs');
const Promise = require('bluebird');

const f = require('../../net2/Firewalla.js');

Promise.promisifyAll(fs);

const rp = require('request-promise');

class FWDiag {
  constructor() {
    if(instance === null) {
      instance = this;
    }

    return instance;
  }

  getEndpoint() {
    return fConfig.firewallaDiagServerURL || `https://api.firewalla.com/diag/api/v1/device/`
  }

  async getGatewayMac(gatewayIP) {
    const pingCmd = `ping -q -c 1 -w 2 ${gatewayIP} || /bin/true`;
    await exec(pingCmd);

    const arpCmd = `arp -a -n | grep ${gatewayIP} -w | awk '{print $4}'`;
    const result = await exec(arpCmd);
    const mac = result.stdout;
    if(mac) {
      return mac.substring(0, 11);
    } else {
      return null;
    }
  }

  async getGatewayName(gatewayIP) {
    const cmd = `arp ${gatewayIP} | tail -n 1 | awk '{print $1}'`;
    // return empty if command execute failed
    const result = await exec(cmd).catch(() => "");
    const name = result.stdout;
    return name.replace(/\n$/, '')
  }

  async getBranchInfo() {
    const result = await exec("git rev-parse --abbrev-ref HEAD");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  getVersion() {
    return fConfig.version;
  }

  async getLongVersion() {
    const result = await exec("git describe --tags");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async getTotalMemory() {
    const result = await exec("free -m | awk '/Mem:/ {print $2}'");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async getGID() {
    const result = await exec("redis-cli hget sys:ept gid");
    return result && result.stdout && result.stdout.replace(/\n$/, '')
  }

  async hasLicenseFile() {
    const filePath = `${f.getHiddenFolder()}/license`;
    try {
      await fs.accessAsync(filePath, fs.constants.F_OK);
      return true;
    } catch (err) {
      return false;
    }
  }

  async prepareData(payload) {
    const inter = sysManager.getDefaultWanInterface()

    const ip = inter.ip_address;
    const gateway = inter.gateway_ip;
    const mac = platform.getSignatureMac();

    const gatewayMac = await this.getGatewayMac(gateway);
    const gatewayName = await this.getGatewayName(gateway);

    const ts = Math.floor(new Date() / 1000);

    return Object.assign({}, payload, {
      gw: gateway,
      fw: ip,
      mac: mac,
      ts: ts,
      gw_mac: gatewayMac,
      gw_name: gatewayName,
      model: model
    });
  }

  async submitInfo(payload) {
    const data = await this.prepareData(payload);
    if(data.gw) {
      const rclient = require('../../util/redis_manager.js').getRedisClient();

      const options = {
        uri:  this.getEndpoint() + data.gw,
        method: 'POST',
        json: data
      }
      const result = await rp(options);
      if(result && result.mode) {
        await rclient.setAsync("recommend_firewalla_mode", result.mode);
      }

      if(result && result.guessedRouter) {
        await rclient.setAsync("guessed_router", JSON.stringify(result.guessedRouter));
      }

      log.info(`submitted ${payload.event} info to diag server successfully with result ${JSON.stringify(result)}`);
    }
  }

  async getCpuTemperature() {
    try {
      return platform.getCpuTemperature()
    } catch(err) {
      return -1;
    }
  }

  async prepareHelloData() {
    const inter = sysManager.getDefaultWanInterface()

    const firewallaIP = inter.ip_address;
    const mac = platform.getSignatureMac();
    const gateway = inter.gateway_ip;

    const version = this.getVersion();

    const [gatewayMac, branch, longVersion, memory, gid, hasLicense, nicSpeed, cpuTemp] =
      await Promise.all([
        this.getGatewayMac(gateway),
        this.getBranchInfo(),
        this.getLongVersion(),
        this.getTotalMemory(),
        this.getGID(),
        this.hasLicenseFile(),
        platform.getNetworkSpeed(),
        this.getCpuTemperature()
      ]);

    return {
      mac,
      firewallaIP,
      gatewayMac,
      branch,
      version,
      longVersion,
      memory,
      model,
      serial,
      gid,
      hasLicense,
      nicSpeed,
      cpuTemp
    };
  }

  async sayHello() {
    const data = await this.prepareHelloData();
    const options = {
      uri: this.getEndpoint() + 'hello',
      method: 'POST',
      json: data
    }
    await rp(options);
    log.info("said hello to Firewalla Cloud");
  }

  async log(level, data) {
    const sysData = await this.prepareHelloData();
    const options = {
      uri: this.getEndpoint() + 'log/' + level,
      method: 'POST',
      json: Object.assign({}, data, sysData)
    }
    log.info(`Sending diag log, [${level}] ${JSON.stringify(data)}`);
    await rp(options);
  }
}

module.exports = new FWDiag();
<|endoftext|>


<commit_before>$(function() {
  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});<commit_msg>smoothscroll: consider nav for offset<commit_after>$(function() {
  $('a[href*="#"]:not([href="#"])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html, body').animate({
          scrollTop: target.offset().top - 45 // Little more than the nav's height
        }, 1000);
        return false;
      }
    }
  });
});<|endoftext|>


<commit_before>(function (window, document) {
  var iframe, doc;

  window.JSCONSOLE = {
    contentWindow: window,
    contentDocument: document,
    console: iframe
  };

  if (iframe = document.getElementById('jsconsole')) {
    document.getElementById('jsconsole').style.display = 'block';
  } else {
    iframe = document.createElement('iframe');

    document.body.appendChild(iframe);

    iframe.id = 'jsconsole';
    iframe.style.display = 'block';
    iframe.style.background = '#fff';
    iframe.style.zIndex = '9999';
    iframe.style.position = 'absolute';
    iframe.style.top = '0px';
    iframe.style.left = '0px';
    iframe.style.width = '100%';
    iframe.style.height = '100%';
    iframe.style.border = '0';

    doc = iframe.contentDocument || iframe.contentWindow.document;

    doc.open();
    doc.write('<!DOCTYPE html><title>jsconsole</title><meta id="meta" name="viewport" content="width=device-width; height=device-height; user-scalable=no; initial-scale=1.0" /><link rel="stylesheet" href="http://jsconsole.com/console.css" type="text/css" /><form><textarea autofocus id="exec" spellcheck="false" autocapitalize="off" autofocus rows="1"></textarea></form>

Fork on Github • Built by @rem
');
    doc.close();

    iframe.contentWindow.onload = function () {
      this.document.getElementById('exec').focus();
    }
  }
})(this, document);<commit_msg>Wrong github repo in inject, Closes #15<commit_after>(function (window, document) {
  var iframe, doc;

  window.JSCONSOLE = {
    contentWindow: window,
    contentDocument: document,
    console: iframe
  };

  if (iframe = document.getElementById('jsconsole')) {
    document.getElementById('jsconsole').style.display = 'block';
  } else {
    iframe = document.createElement('iframe');

    document.body.appendChild(iframe);

    iframe.id = 'jsconsole';
    iframe.style.display = 'block';
    iframe.style.background = '#fff';
    iframe.style.zIndex = '9999';
    iframe.style.position = 'absolute';
    iframe.style.top = '0px';
    iframe.style.left = '0px';
    iframe.style.width = '100%';
    iframe.style.height = '100%';
    iframe.style.border = '0';

    doc = iframe.contentDocument || iframe.contentWindow.document;

    doc.open();
    doc.write('<!DOCTYPE html><title>jsconsole</title><meta id="meta" name="viewport" content="width=device-width; height=device-height; user-scalable=no; initial-scale=1.0" /><link rel="stylesheet" href="http://jsconsole.com/console.css" type="text/css" /><form><textarea autofocus id="exec" spellcheck="false" autocapitalize="off" autofocus rows="1"></textarea></form>

Fork on Github • Built by @rem
');
    doc.close();

    iframe.contentWindow.onload = function () {
      this.document.getElementById('exec').focus();
    }
  }
})(this, document);
<|endoftext|>