Bug 1184917 - Implement the refreshed design for 'Edit' conversation toolbar button. r=mdeboer

This commit is contained in:
Marina Rodriguez Iglesias 2015-08-25 08:23:00 -04:00
Родитель b4d9e4c989
Коммит 67e57121a1
15 изменённых файлов: 531 добавлений и 52 удалений

Просмотреть файл

@ -583,6 +583,7 @@ loop.conversationViews = (function(mozL10n) {
// This is used from the props rather than the state to make it easier for
// the ui-showcase.
mediaConnected: React.PropTypes.bool,
mozLoop: React.PropTypes.object,
remotePosterUrl: React.PropTypes.string,
remoteVideoEnabled: React.PropTypes.bool,
// local
@ -680,6 +681,16 @@ loop.conversationViews = (function(mozL10n) {
},
render: function() {
// 'visible' and 'enabled' are true by default.
var settingsMenuItems = [
{
id: "edit",
visible: false,
enabled: false
},
{ id: "feedback" },
{ id: "help" }
];
return (
React.createElement("div", {className: "desktop-call-wrapper"},
React.createElement(sharedViews.MediaLayoutView, {
@ -702,9 +713,10 @@ loop.conversationViews = (function(mozL10n) {
React.createElement(loop.shared.views.ConversationToolbar, {
audio: this.props.audio,
dispatcher: this.props.dispatcher,
edit: { visible: false, enabled: false},
hangup: this.hangup,
mozLoop: this.props.mozLoop,
publishStream: this.publishStream,
settingsMenuItems: settingsMenuItems,
video: this.props.video})
)
)
@ -807,6 +819,7 @@ loop.conversationViews = (function(mozL10n) {
conversationStore: this.getStore(),
dispatcher: this.props.dispatcher,
mediaConnected: this.state.mediaConnected,
mozLoop: this.props.mozLoop,
remoteSrcVideoObject: this.state.remoteSrcVideoObject,
remoteVideoEnabled: this.state.remoteVideoEnabled,
video: { enabled: !this.state.videoMuted, visible: true}})

Просмотреть файл

@ -583,6 +583,7 @@ loop.conversationViews = (function(mozL10n) {
// This is used from the props rather than the state to make it easier for
// the ui-showcase.
mediaConnected: React.PropTypes.bool,
mozLoop: React.PropTypes.object,
remotePosterUrl: React.PropTypes.string,
remoteVideoEnabled: React.PropTypes.bool,
// local
@ -680,6 +681,16 @@ loop.conversationViews = (function(mozL10n) {
},
render: function() {
// 'visible' and 'enabled' are true by default.
var settingsMenuItems = [
{
id: "edit",
visible: false,
enabled: false
},
{ id: "feedback" },
{ id: "help" }
];
return (
<div className="desktop-call-wrapper">
<sharedViews.MediaLayoutView
@ -702,9 +713,10 @@ loop.conversationViews = (function(mozL10n) {
<loop.shared.views.ConversationToolbar
audio={this.props.audio}
dispatcher={this.props.dispatcher}
edit={{ visible: false, enabled: false }}
hangup={this.hangup}
mozLoop={this.props.mozLoop}
publishStream={this.publishStream}
settingsMenuItems={settingsMenuItems}
video={this.props.video} />
</sharedViews.MediaLayoutView>
</div>
@ -807,6 +819,7 @@ loop.conversationViews = (function(mozL10n) {
conversationStore={this.getStore()}
dispatcher={this.props.dispatcher}
mediaConnected={this.state.mediaConnected}
mozLoop={this.props.mozLoop}
remoteSrcVideoObject={this.state.remoteSrcVideoObject}
remoteVideoEnabled={this.state.remoteVideoEnabled}
video={{ enabled: !this.state.videoMuted, visible: true }} />

Просмотреть файл

@ -724,6 +724,16 @@ loop.roomViews = (function(mozL10n) {
return null;
}
default: {
var settingsMenuItems = [
{
id: "edit",
enabled: !this.state.showEditContext,
visible: this.state.contextEnabled,
onClick: this.handleEditContextClick
},
{ id: "feedback" },
{ id: "help" }
];
return (
React.createElement("div", {className: "room-conversation-wrapper desktop-room-wrapper"},
React.createElement(sharedViews.MediaLayoutView, {
@ -746,11 +756,11 @@ loop.roomViews = (function(mozL10n) {
React.createElement(sharedViews.ConversationToolbar, {
audio: {enabled: !this.state.audioMuted, visible: true},
dispatcher: this.props.dispatcher,
edit: { visible: this.state.contextEnabled, enabled: !this.state.showEditContext},
hangup: this.leaveRoom,
onEditClick: this.handleEditContextClick,
mozLoop: this.props.mozLoop,
publishStream: this.publishStream,
screenShare: screenShareData,
settingsMenuItems: settingsMenuItems,
video: {enabled: !this.state.videoMuted, visible: true}}),
React.createElement(DesktopRoomInvitationView, {
dispatcher: this.props.dispatcher,

Просмотреть файл

@ -724,6 +724,16 @@ loop.roomViews = (function(mozL10n) {
return null;
}
default: {
var settingsMenuItems = [
{
id: "edit",
enabled: !this.state.showEditContext,
visible: this.state.contextEnabled,
onClick: this.handleEditContextClick
},
{ id: "feedback" },
{ id: "help" }
];
return (
<div className="room-conversation-wrapper desktop-room-wrapper">
<sharedViews.MediaLayoutView
@ -746,11 +756,11 @@ loop.roomViews = (function(mozL10n) {
<sharedViews.ConversationToolbar
audio={{enabled: !this.state.audioMuted, visible: true}}
dispatcher={this.props.dispatcher}
edit={{ visible: this.state.contextEnabled, enabled: !this.state.showEditContext }}
hangup={this.leaveRoom}
onEditClick={this.handleEditContextClick}
mozLoop={this.props.mozLoop}
publishStream={this.publishStream}
screenShare={screenShareData}
settingsMenuItems={settingsMenuItems}
video={{enabled: !this.state.videoMuted, visible: true}} />
<DesktopRoomInvitationView
dispatcher={this.props.dispatcher}

Просмотреть файл

@ -203,15 +203,15 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
content: url("../img/svg/video-mute-hover.svg");
}
.btn-mute-edit {
.btn-settings {
width: 28px;
height: 28px;
background-size: 28px;
background-image: url("../img/svg/settings.svg");
}
.btn-mute-edit:hover,
.btn-mute-edit:active {
.btn-settings:hover,
.btn-settings:active {
background-image: url("../img/svg/settings-hover.svg");
}
@ -224,7 +224,7 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
background-image: url("../img/svg/sharing-hover.svg");
}
.btn-mute-edit.muted,
.btn-settings.muted,
.btn-screen-share.active {
opacity: 1;
}
@ -385,6 +385,17 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
white-space: nowrap;
}
.settings-menu.dropdown-menu {
left: auto;
bottom: 3.1rem;
right: 14px;
}
html[dir="rtl"] .settings-menu.dropdown-menu {
left: 14px;
right: auto;
}
/* Expired call url page */
.expired-url-info {
@ -1228,6 +1239,12 @@ html[dir="rtl"] .room-context-btn-close {
height: 30%;
}
.media-wrapper.receiving-screen-share > .remote > .conversation-toolbar,
.media-wrapper.showing-local-streams.receiving-screen-share > .remote > .conversation-toolbar {
bottom: calc(30% + 1.5rem);
}
.desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view,
.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view {
/* This is temp, to echo the .media-wrapper > .text-chat-view above */

Просмотреть файл

@ -180,6 +180,146 @@ loop.shared.views = (function(_, mozL10n) {
}
});
/**
* Settings control button.
*/
var SettingsControlButton = React.createClass({displayName: "SettingsControlButton",
propTypes: {
menuItems: React.PropTypes.array,
mozLoop: React.PropTypes.object
},
mixins: [
sharedMixins.DropdownMenuMixin(),
React.addons.PureRenderMixin
],
/**
* Show or hide the settings menu
*/
handleClick: function(event) {
event.preventDefault();
this.toggleDropdownMenu();
},
/**
* Return the function that Show or hide the edit context edition form
*/
getHandleToggleEdit: function(editItem) {
return function _handleToglleEdit(event) {
event.preventDefault();
if (editItem.onClick) {
editItem.onClick(!editItem.enabled);
}
};
},
/**
* Load on the browser the help (support) url from prefs
*/
handleHelpEntry: function(event) {
event.preventDefault();
var helloSupportUrl = this.props.mozLoop.getLoopPref("support_url");
this.props.mozLoop.openURL(helloSupportUrl);
},
/**
* Load on the browser the feedback url from prefs
*/
handleSubmitFeedback: function(event) {
event.preventDefault();
var helloFeedbackUrl = this.props.mozLoop.getLoopPref("feedback.formURL");
this.props.mozLoop.openURL(helloFeedbackUrl);
},
/**
* Recover the needed info for generating an specific menu Item
*/
getItemInfo: function(menuItem) {
var cx = React.addons.classSet;
switch (menuItem.id) {
case "feedback":
return {
cssClasses: "dropdown-menu-item",
handler: this.handleSubmitFeedback,
label: mozL10n.get("feedback_request_button")
};
case "help":
return {
cssClasses: "dropdown-menu-item",
handler: this.handleHelpEntry,
label: mozL10n.get("help_label")
};
case "edit":
return {
cssClasses: cx({
"dropdown-menu-item": true,
"entry-settings-edit": true,
"hide": !menuItem.visible
}),
handler: this.getHandleToggleEdit(menuItem),
label: mozL10n.get(menuItem.enabled ?
"conversation_settings_menu_edit_context" :
"conversation_settings_menu_hide_context"),
scope: "local",
type: "edit"
};
default:
console.error("Invalid menu item", menuItem);
return null;
}
},
/**
* Generate a menu item after recover its info
*/
generateMenuItem: function(menuItem) {
var itemInfo = this.getItemInfo(menuItem);
if (!itemInfo) {
return null;
}
return (
React.createElement("li", {className: itemInfo.cssClasses,
key: menuItem.id,
onClick: itemInfo.handler,
scope: itemInfo.scope || "",
type: itemInfo.type || ""},
itemInfo.label
)
);
},
render: function() {
if (!this.props.menuItems || !this.props.menuItems.length) {
return null;
}
var menuItemRows = this.props.menuItems.map(this.generateMenuItem)
.filter(function(item) { return item; });
if (!menuItemRows || !menuItemRows.length) {
return null;
}
var cx = React.addons.classSet;
var settingsDropdownMenuClasses = cx({
"settings-menu": true,
"dropdown-menu": true,
"hide": !this.state.showMenu
});
return (
React.createElement("div", null,
React.createElement("button", {className: "btn btn-settings transparent-button",
onClick: this.toggleDropdownMenu,
ref: "menu-button",
title: mozL10n.get("settings_menu_button_tooltip")}),
React.createElement("ul", {className: settingsDropdownMenuClasses, ref: "menu"},
menuItemRows
)
)
);
}
});
/**
* Conversation controls.
*/
@ -188,8 +328,8 @@ loop.shared.views = (function(_, mozL10n) {
return {
video: {enabled: true, visible: true},
audio: {enabled: true, visible: true},
edit: {enabled: false, visible: false},
screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
settingsMenuItems: null,
enableHangup: true
};
},
@ -203,13 +343,13 @@ loop.shared.views = (function(_, mozL10n) {
propTypes: {
audio: React.PropTypes.object.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
edit: React.PropTypes.object.isRequired,
enableHangup: React.PropTypes.bool,
hangup: React.PropTypes.func.isRequired,
hangupButtonLabel: React.PropTypes.string,
onEditClick: React.PropTypes.func,
mozLoop: React.PropTypes.object,
publishStream: React.PropTypes.func.isRequired,
screenShare: React.PropTypes.object,
settingsMenuItems: React.PropTypes.array,
video: React.PropTypes.object.isRequired
},
@ -225,12 +365,6 @@ loop.shared.views = (function(_, mozL10n) {
this.props.publishStream("audio", !this.props.audio.enabled);
},
handleToggleEdit: function() {
if (this.props.onEditClick) {
this.props.onEditClick(!this.props.edit.enabled);
}
},
componentDidMount: function() {
this.userActivity = false;
this.startIdleCountDown();
@ -326,7 +460,6 @@ loop.shared.views = (function(_, mozL10n) {
enabled: this.props.audio.enabled,
scope: "local", type: "audio",
visible: this.props.audio.visible})
)
),
React.createElement("li", {className: "conversation-toolbar-btn-box"},
@ -335,13 +468,8 @@ loop.shared.views = (function(_, mozL10n) {
visible: this.props.screenShare.visible})
),
React.createElement("li", {className: "conversation-toolbar-btn-box btn-edit-entry"},
React.createElement(MediaControlButton, {action: this.handleToggleEdit,
enabled: this.props.edit.enabled,
scope: "local",
title: mozL10n.get(this.props.edit.enabled ?
"context_edit_tooltip" : "context_hide_tooltip"),
type: "edit",
visible: this.props.edit.visible})
React.createElement(SettingsControlButton, {menuItems: this.props.settingsMenuItems,
mozLoop: this.props.mozLoop})
)
)
);
@ -364,6 +492,7 @@ loop.shared.views = (function(_, mozL10n) {
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool,
model: React.PropTypes.object.isRequired,
mozLoop: React.PropTypes.object,
sdk: React.PropTypes.object.isRequired,
video: React.PropTypes.object
},
@ -559,6 +688,7 @@ loop.shared.views = (function(_, mozL10n) {
audio: this.state.audio,
dispatcher: this.props.dispatcher,
hangup: this.hangup,
mozLoop: this.props.mozLoop,
publishStream: this.publishStream,
video: this.state.video})
)
@ -1176,6 +1306,7 @@ loop.shared.views = (function(_, mozL10n) {
MediaLayoutView: MediaLayoutView,
MediaView: MediaView,
LoadingView: LoadingView,
SettingsControlButton: SettingsControlButton,
ScreenShareControlButton: ScreenShareControlButton,
NotificationListView: NotificationListView
};

Просмотреть файл

@ -180,6 +180,146 @@ loop.shared.views = (function(_, mozL10n) {
}
});
/**
* Settings control button.
*/
var SettingsControlButton = React.createClass({
propTypes: {
menuItems: React.PropTypes.array,
mozLoop: React.PropTypes.object
},
mixins: [
sharedMixins.DropdownMenuMixin(),
React.addons.PureRenderMixin
],
/**
* Show or hide the settings menu
*/
handleClick: function(event) {
event.preventDefault();
this.toggleDropdownMenu();
},
/**
* Return the function that Show or hide the edit context edition form
*/
getHandleToggleEdit: function(editItem) {
return function _handleToglleEdit(event) {
event.preventDefault();
if (editItem.onClick) {
editItem.onClick(!editItem.enabled);
}
};
},
/**
* Load on the browser the help (support) url from prefs
*/
handleHelpEntry: function(event) {
event.preventDefault();
var helloSupportUrl = this.props.mozLoop.getLoopPref("support_url");
this.props.mozLoop.openURL(helloSupportUrl);
},
/**
* Load on the browser the feedback url from prefs
*/
handleSubmitFeedback: function(event) {
event.preventDefault();
var helloFeedbackUrl = this.props.mozLoop.getLoopPref("feedback.formURL");
this.props.mozLoop.openURL(helloFeedbackUrl);
},
/**
* Recover the needed info for generating an specific menu Item
*/
getItemInfo: function(menuItem) {
var cx = React.addons.classSet;
switch (menuItem.id) {
case "feedback":
return {
cssClasses: "dropdown-menu-item",
handler: this.handleSubmitFeedback,
label: mozL10n.get("feedback_request_button")
};
case "help":
return {
cssClasses: "dropdown-menu-item",
handler: this.handleHelpEntry,
label: mozL10n.get("help_label")
};
case "edit":
return {
cssClasses: cx({
"dropdown-menu-item": true,
"entry-settings-edit": true,
"hide": !menuItem.visible
}),
handler: this.getHandleToggleEdit(menuItem),
label: mozL10n.get(menuItem.enabled ?
"conversation_settings_menu_edit_context" :
"conversation_settings_menu_hide_context"),
scope: "local",
type: "edit"
};
default:
console.error("Invalid menu item", menuItem);
return null;
}
},
/**
* Generate a menu item after recover its info
*/
generateMenuItem: function(menuItem) {
var itemInfo = this.getItemInfo(menuItem);
if (!itemInfo) {
return null;
}
return (
<li className={itemInfo.cssClasses}
key={menuItem.id}
onClick={itemInfo.handler}
scope={itemInfo.scope || ""}
type={itemInfo.type || ""} >
{itemInfo.label}
</li>
);
},
render: function() {
if (!this.props.menuItems || !this.props.menuItems.length) {
return null;
}
var menuItemRows = this.props.menuItems.map(this.generateMenuItem)
.filter(function(item) { return item; });
if (!menuItemRows || !menuItemRows.length) {
return null;
}
var cx = React.addons.classSet;
var settingsDropdownMenuClasses = cx({
"settings-menu": true,
"dropdown-menu": true,
"hide": !this.state.showMenu
});
return (
<div>
<button className="btn btn-settings transparent-button"
onClick={this.toggleDropdownMenu}
ref="menu-button"
title={mozL10n.get("settings_menu_button_tooltip")} />
<ul className={settingsDropdownMenuClasses} ref="menu">
{menuItemRows}
</ul>
</div>
);
}
});
/**
* Conversation controls.
*/
@ -188,8 +328,8 @@ loop.shared.views = (function(_, mozL10n) {
return {
video: {enabled: true, visible: true},
audio: {enabled: true, visible: true},
edit: {enabled: false, visible: false},
screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
settingsMenuItems: null,
enableHangup: true
};
},
@ -203,13 +343,13 @@ loop.shared.views = (function(_, mozL10n) {
propTypes: {
audio: React.PropTypes.object.isRequired,
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
edit: React.PropTypes.object.isRequired,
enableHangup: React.PropTypes.bool,
hangup: React.PropTypes.func.isRequired,
hangupButtonLabel: React.PropTypes.string,
onEditClick: React.PropTypes.func,
mozLoop: React.PropTypes.object,
publishStream: React.PropTypes.func.isRequired,
screenShare: React.PropTypes.object,
settingsMenuItems: React.PropTypes.array,
video: React.PropTypes.object.isRequired
},
@ -225,12 +365,6 @@ loop.shared.views = (function(_, mozL10n) {
this.props.publishStream("audio", !this.props.audio.enabled);
},
handleToggleEdit: function() {
if (this.props.onEditClick) {
this.props.onEditClick(!this.props.edit.enabled);
}
},
componentDidMount: function() {
this.userActivity = false;
this.startIdleCountDown();
@ -326,7 +460,6 @@ loop.shared.views = (function(_, mozL10n) {
enabled={this.props.audio.enabled}
scope="local" type="audio"
visible={this.props.audio.visible}/>
</div>
</li>
<li className="conversation-toolbar-btn-box">
@ -335,13 +468,8 @@ loop.shared.views = (function(_, mozL10n) {
visible={this.props.screenShare.visible} />
</li>
<li className="conversation-toolbar-btn-box btn-edit-entry">
<MediaControlButton action={this.handleToggleEdit}
enabled={this.props.edit.enabled}
scope="local"
title={mozL10n.get(this.props.edit.enabled ?
"context_edit_tooltip" : "context_hide_tooltip")}
type="edit"
visible={this.props.edit.visible} />
<SettingsControlButton menuItems={this.props.settingsMenuItems}
mozLoop={this.props.mozLoop} />
</li>
</ul>
);
@ -364,6 +492,7 @@ loop.shared.views = (function(_, mozL10n) {
initiate: React.PropTypes.bool,
isDesktop: React.PropTypes.bool,
model: React.PropTypes.object.isRequired,
mozLoop: React.PropTypes.object,
sdk: React.PropTypes.object.isRequired,
video: React.PropTypes.object
},
@ -559,6 +688,7 @@ loop.shared.views = (function(_, mozL10n) {
audio={this.state.audio}
dispatcher={this.props.dispatcher}
hangup={this.hangup}
mozLoop={this.props.mozLoop}
publishStream={this.publishStream}
video={this.state.video} />
</div>
@ -1176,6 +1306,7 @@ loop.shared.views = (function(_, mozL10n) {
MediaLayoutView: MediaLayoutView,
MediaView: MediaView,
LoadingView: LoadingView,
SettingsControlButton: SettingsControlButton,
ScreenShareControlButton: ScreenShareControlButton,
NotificationListView: NotificationListView
};

Просмотреть файл

@ -524,7 +524,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
audio: {enabled: !this.state.audioMuted,
visible: this._roomIsActive()},
dispatcher: this.props.dispatcher,
edit: { visible: false, enabled: false},
enableHangup: this._roomIsActive(),
hangup: this.leaveRoom,
hangupButtonLabel: mozL10n.get("rooms_leave_button_label"),

Просмотреть файл

@ -524,7 +524,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
audio={{enabled: !this.state.audioMuted,
visible: this._roomIsActive()}}
dispatcher={this.props.dispatcher}
edit={{ visible: false, enabled: false }}
enableHangup={this._roomIsActive()}
hangup={this.leaveRoom}
hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}

Просмотреть файл

@ -479,6 +479,7 @@ describe("loop.conversationViews", function () {
var props = _.extend({
conversationStore: conversationStore,
dispatcher: dispatcher,
mozLoop: {},
matchMedia: window.matchMedia
}, extraProps);
return TestUtils.renderIntoDocument(

Просмотреть файл

@ -605,7 +605,7 @@ describe("loop.roomViews", function () {
expect(node.querySelector(".room-context")).to.eql(null);
var editButton = node.querySelector(".btn-mute-edit");
var editButton = node.querySelector(".settings-menu > li.entry-settings-edit");
React.addons.TestUtils.Simulate.click(editButton);
expect(view.getDOMNode().querySelector(".room-context")).to.not.eql(null);
@ -614,7 +614,7 @@ describe("loop.roomViews", function () {
it("should hide the form when the edit button is clicked again", function() {
view = mountTestComponent();
var editButton = view.getDOMNode().querySelector(".btn-mute-edit");
var editButton = view.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
React.addons.TestUtils.Simulate.click(editButton);
// Click again.

Просмотреть файл

@ -252,12 +252,159 @@ describe("loop.shared.views", function() {
});
});
describe("SettingsControlButton", function() {
var fakeMozLoop;
var support_url = "https://support.com";
var feedback_url = "https://feedback.com";
beforeEach(function() {
fakeMozLoop = {
openURL: sandbox.stub(),
setLoopPref: sandbox.stub(),
getLoopPref: function (prefName) {
switch (prefName) {
case "support_url":
return support_url;
case "feedback.formURL":
return feedback_url;
default:
return prefName;
}
}
};
});
function mountTestComponent(props) {
props = _.extend({
mozLoop: fakeMozLoop
}, props);
return TestUtils.renderIntoDocument(
React.createElement(sharedViews.SettingsControlButton, props));
}
it("should render a visible button", function() {
var settingsMenuItems = [{ id: "feedback" }];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
var node = comp.getDOMNode().querySelector(".btn-settings");
expect(node.classList.contains("hide")).eql(false);
});
it("should not render anything", function() {
var comp = mountTestComponent();
expect(comp.getDOMNode()).to.eql(null);
});
it("should not show an indefined menu option", function() {
var settingsMenuItems = [
{ id: "not Defined" },
{ id: "help" }
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
var menuItems = comp.getDOMNode().querySelectorAll(".settings-menu > li");
expect(menuItems).to.have.length.of(1);
});
it("should not render anythin if not exists any valid item to show", function() {
var settingsMenuItems = [
{ id: "not Defined" },
{ id: "another wrong menu item" }
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
expect(comp.getDOMNode()).to.eql(null);
});
it("should show the settings dropdown on click", function() {
var settingsMenuItems = [{ id: "feedback" }];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
expect(comp.state.showMenu).eql(false);
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".btn-settings"));
expect(comp.state.showMenu).eql(true);
});
it("should show edit Context on menu when the option is enabled", function() {
var settingsMenuItems = [
{
id: "edit",
enabled: true,
visible: true,
onClick: function() {}
}
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
var node = comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
expect(node.classList.contains("hide")).eql(false);
});
it("should hide edit Context on menu when the option is not visible", function() {
var settingsMenuItems = [
{
id: "edit",
enabled: false,
visible: false,
onClick: function() {}
}
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
var node = comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
expect(node.classList.contains("hide")).eql(true);
});
it("should call onClick method when the edit context menu item is clicked", function() {
var onClickCalled = false;
var settingsMenuItems = [
{
id: "edit",
enabled: true,
visible: true,
onClick: sandbox.stub()
}
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit"));
sinon.assert.calledOnce(settingsMenuItems[0].onClick);
});
it("should open a tab to the feedback url when the feedback menu item is clicked", function() {
var settingsMenuItems = [
{ id: "feedback" },
{ id: "help" }
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li:first-child"));
sinon.assert.calledOnce(fakeMozLoop.openURL);
sinon.assert.calledWithExactly(fakeMozLoop.openURL, feedback_url);
});
it("should open a tab to the support url when the support menu item is clicked", function() {
var settingsMenuItems = [
{ id: "feedback" },
{ id: "help" }
];
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li:last-child"));
sinon.assert.calledOnce(fakeMozLoop.openURL);
sinon.assert.calledWithExactly(fakeMozLoop.openURL, support_url);
});
});
describe("ConversationToolbar", function() {
var clock, hangup, publishStream;
function mountTestComponent(props) {
props = _.extend({
dispatcher: dispatcher
dispatcher: dispatcher,
mozLoop: {}
}, props || {});
return TestUtils.renderIntoDocument(
React.createElement(sharedViews.ConversationToolbar, props));
@ -407,7 +554,8 @@ describe("loop.shared.views", function() {
function mountTestComponent(props) {
props = _.extend({
dispatcher: dispatcher
dispatcher: dispatcher,
mozLoop: {}
}, props || {});
return TestUtils.renderIntoDocument(
React.createElement(sharedViews.ConversationView, props));

Просмотреть файл

@ -1028,6 +1028,7 @@
React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true},
hangup: noop,
publishStream: noop,
settingsMenuItems: [{ id: "feedback" }],
video: { enabled: true, visible: true}})
)
),
@ -1039,6 +1040,7 @@
React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true},
hangup: noop,
publishStream: noop,
settingsMenuItems: [{ id: "feedback" }],
video: { enabled: false, visible: true}})
)
),
@ -1050,6 +1052,7 @@
React.createElement(ConversationToolbar, {audio: { enabled: false, visible: true},
hangup: noop,
publishStream: noop,
settingsMenuItems: [{ id: "feedback" }],
video: { enabled: true, visible: true}})
)
)

Просмотреть файл

@ -1028,6 +1028,7 @@
<ConversationToolbar audio={{ enabled: true, visible: true }}
hangup={noop}
publishStream={noop}
settingsMenuItems={[{ id: "feedback" }]}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
@ -1039,6 +1040,7 @@
<ConversationToolbar audio={{ enabled: true, visible: true }}
hangup={noop}
publishStream={noop}
settingsMenuItems={[{ id: "feedback" }]}
video={{ enabled: false, visible: true }} />
</div>
</FramedExample>
@ -1050,6 +1052,7 @@
<ConversationToolbar audio={{ enabled: false, visible: true }}
hangup={noop}
publishStream={noop}
settingsMenuItems={[{ id: "feedback" }]}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>

Просмотреть файл

@ -357,12 +357,13 @@ context_edit_activate_label=Talk about "{{title}}"
context_edit_name_placeholder=Conversation Name
context_edit_comments_placeholder=Comments
context_add_some_label=Add some context
context_edit_tooltip=Edit Context
context_hide_tooltip=Hide Context
context_show_tooltip=Show Context
context_save_label2=Save
context_link_modified=This link was modified.
context_learn_more_link_label=Learn more.
conversation_settings_menu_edit_context=Edit Context
conversation_settings_menu_hide_context=Hide Context
# Text chat strings