Create Support Requests from Flipper
Summary: This diff adds an initial support to prefill the app information and the revision information. This diff also copies the workplace url in the clipboard. Reviewed By: passy Differential Revision: D16990925 fbshipit-source-id: 4f354e52de5fea07c2ea36336761d6963c27ef66
This commit is contained in:
committed by
Facebook Github Bot
parent
b041da6d61
commit
84c5067210
11
src/App.tsx
11
src/App.tsx
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {FlexColumn, FlexRow} from 'flipper';
|
||||
import {FlexColumn, FlexRow, Client} from 'flipper';
|
||||
import {connect} from 'react-redux';
|
||||
import TitleBar from './chrome/TitleBar';
|
||||
import MainSidebar from './chrome/MainSidebar';
|
||||
@@ -35,6 +35,7 @@ import BugReporter from './fb-stubs/BugReporter';
|
||||
import {State as Store} from './reducers/index';
|
||||
import {StaticView} from './reducers/connections';
|
||||
import PluginManager from './chrome/PluginManager';
|
||||
import BaseDevice from './devices/BaseDevice';
|
||||
const version = remote.app.getVersion();
|
||||
|
||||
type OwnProps = {
|
||||
@@ -48,6 +49,8 @@ type StateFromProps = {
|
||||
activeSheet: ActiveSheet;
|
||||
share: ShareType | null;
|
||||
staticView: StaticView;
|
||||
clients: Array<Client>;
|
||||
selectedDevice: null | BaseDevice;
|
||||
};
|
||||
|
||||
type Props = StateFromProps & OwnProps;
|
||||
@@ -114,7 +117,7 @@ export class App extends React.Component<Props> {
|
||||
<FlexRow grow={true}>
|
||||
{this.props.leftSidebarVisible && <MainSidebar />}
|
||||
{this.props.staticView != null ? (
|
||||
React.createElement(this.props.staticView)
|
||||
React.createElement(this.props.staticView, this.props)
|
||||
) : (
|
||||
<PluginContainer logger={this.props.logger} />
|
||||
)}
|
||||
@@ -128,12 +131,14 @@ export class App extends React.Component<Props> {
|
||||
export default connect<StateFromProps, {}, OwnProps, Store>(
|
||||
({
|
||||
application: {leftSidebarVisible, activeSheet, share},
|
||||
connections: {error, staticView},
|
||||
connections: {error, staticView, clients, selectedDevice},
|
||||
}) => ({
|
||||
leftSidebarVisible,
|
||||
activeSheet,
|
||||
share: share,
|
||||
error,
|
||||
staticView,
|
||||
clients,
|
||||
selectedDevice,
|
||||
}),
|
||||
)(App);
|
||||
|
||||
@@ -13,7 +13,6 @@ import {FlipperBasePlugin} from '../plugin';
|
||||
import {PluginNotification} from '../reducers/notifications';
|
||||
import {ActiveSheet, ACTIVE_SHEET_PLUGINS} from '../reducers/application';
|
||||
import {State as Store} from '../reducers';
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
FlexBox,
|
||||
@@ -30,7 +29,12 @@ import {
|
||||
} from 'flipper';
|
||||
import React, {Component, PureComponent} from 'react';
|
||||
import NotificationsHub from '../NotificationsHub';
|
||||
import {selectPlugin, showMoreOrLessPlugins} from '../reducers/connections';
|
||||
import {
|
||||
selectPlugin,
|
||||
showMoreOrLessPlugins,
|
||||
StaticView,
|
||||
setStaticView,
|
||||
} from '../reducers/connections';
|
||||
import {setActiveSheet} from '../reducers/application';
|
||||
import UserAccount from './UserAccount';
|
||||
import {connect} from 'react-redux';
|
||||
@@ -40,6 +44,7 @@ import {
|
||||
SHOW_REMAINING_PLUGIN_IF_LESS_THAN,
|
||||
} from '../Client';
|
||||
import {StyledOtherComponent} from 'create-emotion-styled';
|
||||
import SupportRequestForm from '../fb-stubs/SupportRequestForm';
|
||||
|
||||
const ListItem = styled('div')(({active}: {active?: boolean}) => ({
|
||||
paddingLeft: 10,
|
||||
@@ -213,6 +218,7 @@ type StateFromProps = {
|
||||
numNotifications: number;
|
||||
windowIsFocused: boolean;
|
||||
selectedDevice: BaseDevice | null | undefined;
|
||||
staticView: StaticView;
|
||||
selectedPlugin: string | null | undefined;
|
||||
selectedApp: string | null | undefined;
|
||||
clients: Array<Client>;
|
||||
@@ -231,9 +237,8 @@ type DispatchFromProps = {
|
||||
selectedApp: string | null;
|
||||
deepLinkPayload: string | null;
|
||||
}) => void;
|
||||
|
||||
setActiveSheet: (activeSheet: ActiveSheet) => void;
|
||||
|
||||
setStaticView: (payload: StaticView) => void;
|
||||
showMoreOrLessPlugins: (payload: string) => void;
|
||||
};
|
||||
|
||||
@@ -243,12 +248,18 @@ class MainSidebar extends PureComponent<Props> {
|
||||
const {
|
||||
selectedDevice,
|
||||
selectedPlugin,
|
||||
staticView,
|
||||
selectedApp,
|
||||
selectPlugin,
|
||||
setStaticView,
|
||||
windowIsFocused,
|
||||
numNotifications,
|
||||
} = this.props;
|
||||
let {clients, uninitializedClients} = this.props;
|
||||
const showLithoForm =
|
||||
GK.get('flipper_support_requests') &&
|
||||
selectedDevice &&
|
||||
selectedDevice.os === 'Android';
|
||||
clients = clients
|
||||
.filter(
|
||||
(client: Client) =>
|
||||
@@ -295,6 +306,25 @@ class MainSidebar extends PureComponent<Props> {
|
||||
</PluginName>
|
||||
</ListItem>
|
||||
)}
|
||||
{showLithoForm && (
|
||||
<ListItem
|
||||
active={staticView != null && staticView === SupportRequestForm}
|
||||
onClick={() => setStaticView(SupportRequestForm)}>
|
||||
<PluginIcon
|
||||
color={colors.light50}
|
||||
name={'bell'}
|
||||
isActive={
|
||||
staticView != null && staticView === SupportRequestForm
|
||||
}
|
||||
/>
|
||||
<PluginName
|
||||
isActive={
|
||||
staticView != null && staticView === SupportRequestForm
|
||||
}>
|
||||
Litho Support Request
|
||||
</PluginName>
|
||||
</ListItem>
|
||||
)}
|
||||
{selectedDevice && (
|
||||
<SidebarHeader>{selectedDevice.title}</SidebarHeader>
|
||||
)}
|
||||
@@ -416,6 +446,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
selectedApp,
|
||||
clients,
|
||||
uninitializedClients,
|
||||
staticView,
|
||||
},
|
||||
notifications: {activeNotifications, blacklistedPlugins},
|
||||
plugins: {devicePlugins, clientPlugins},
|
||||
@@ -428,6 +459,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
})(),
|
||||
windowIsFocused,
|
||||
selectedDevice,
|
||||
staticView,
|
||||
selectedPlugin,
|
||||
selectedApp,
|
||||
clients,
|
||||
@@ -437,6 +469,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
}),
|
||||
{
|
||||
selectPlugin,
|
||||
setStaticView,
|
||||
setActiveSheet,
|
||||
showMoreOrLessPlugins,
|
||||
},
|
||||
|
||||
15
src/fb-stubs/SupportRequestForm.tsx
Normal file
15
src/fb-stubs/SupportRequestForm.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
|
||||
import Text from '../ui/components/FlexRow';
|
||||
import React, {PureComponent} from 'react';
|
||||
|
||||
export default class SupportRequestForm extends PureComponent<void, void> {
|
||||
render() {
|
||||
return <Text> Implement your own Bug creator </Text>;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,12 @@ import {Actions} from '.';
|
||||
const WelcomeScreen = isHeadless()
|
||||
? require('../chrome/WelcomeScreenHeadless').default
|
||||
: require('../chrome/WelcomeScreen').default;
|
||||
export type StaticView = null | typeof WelcomeScreen;
|
||||
import SupportRequestForm from '../fb-stubs/SupportRequestForm';
|
||||
|
||||
export type StaticView =
|
||||
| null
|
||||
| typeof WelcomeScreen
|
||||
| typeof SupportRequestForm;
|
||||
|
||||
export type State = {
|
||||
devices: Array<BaseDevice>;
|
||||
@@ -135,9 +140,11 @@ const reducer = (state: State = INITAL_STATE, action: Actions): State => {
|
||||
switch (action.type) {
|
||||
case 'SET_STATIC_VIEW': {
|
||||
const {payload} = action;
|
||||
const {selectedPlugin} = state;
|
||||
return {
|
||||
...state,
|
||||
staticView: payload,
|
||||
selectedPlugin: payload != null ? null : selectedPlugin,
|
||||
};
|
||||
}
|
||||
case 'SELECT_DEVICE': {
|
||||
@@ -256,6 +263,7 @@ const reducer = (state: State = INITAL_STATE, action: Actions): State => {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
staticView: null,
|
||||
userPreferredApp: userPreferredApp,
|
||||
userPreferredPlugin: selectedPlugin,
|
||||
userLRUPlugins: selectedAppName
|
||||
@@ -452,6 +460,11 @@ export const selectDevice = (payload: BaseDevice): Action => ({
|
||||
payload,
|
||||
});
|
||||
|
||||
export const setStaticView = (payload: StaticView): Action => ({
|
||||
type: 'SET_STATIC_VIEW',
|
||||
payload,
|
||||
});
|
||||
|
||||
export const preferDevice = (payload: string): Action => ({
|
||||
type: 'PREFER_DEVICE',
|
||||
payload,
|
||||
|
||||
38
src/utils/clientUtils.tsx
Normal file
38
src/utils/clientUtils.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
import Client from '../Client';
|
||||
import BaseDevice from '../devices/BaseDevice';
|
||||
|
||||
export function currentActiveApps(
|
||||
clients: Array<Client>,
|
||||
selectedDevice: null | BaseDevice,
|
||||
): Array<string> {
|
||||
const currentActiveApps: Array<string> = clients
|
||||
.map(({id}: {id: string}) => {
|
||||
const appName = appNameFromClienID(id) || '';
|
||||
const device = deviceFromClienID(id) || '';
|
||||
return {appName, device};
|
||||
})
|
||||
.filter(
|
||||
({device}: {device: string}) =>
|
||||
device && selectedDevice && device == selectedDevice.os,
|
||||
)
|
||||
.map(client => client.appName);
|
||||
return currentActiveApps;
|
||||
}
|
||||
|
||||
export function appNameFromClienID(id: string): string | undefined {
|
||||
const arr = id.split('#');
|
||||
const appName = arr[0];
|
||||
return appName;
|
||||
}
|
||||
|
||||
export function deviceFromClienID(id: string): string | undefined {
|
||||
const arr = id.split('#');
|
||||
const device = arr[1];
|
||||
return device;
|
||||
}
|
||||
62
src/utils/supportRequestsFormUtils.tsx
Normal file
62
src/utils/supportRequestsFormUtils.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
import {WebviewTag} from 'electron';
|
||||
|
||||
// TODO: Get rid off this function
|
||||
function injectJavaScript(webview: WebviewTag, command: string): Promise<any> {
|
||||
// @ts-ignore: Typescript doesn't have type src in the currentTarget variable in the event, due to which there is a discrepancy in the event callback.
|
||||
return webview.executeJavaScript(command, false);
|
||||
}
|
||||
|
||||
export function sendDidMountMessage(webview: WebviewTag) {
|
||||
webview.send('hostMessage', {
|
||||
type: 'onMountFlipper',
|
||||
payload: null,
|
||||
});
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param webview
|
||||
* @param text
|
||||
* This helper function is for appending a text in the questions input text field.
|
||||
* One should use it only for the pages backed by NTUsersFormContainer.react.js
|
||||
*/
|
||||
export function appendTextInQuestionsField(webview: WebviewTag, text: string) {
|
||||
webview.send('hostMessage', {
|
||||
type: 'appendQuestionString',
|
||||
payload: text,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param webview
|
||||
* @param data
|
||||
* This helper function is for updating a react state in NTUsersFormContainer.react.js
|
||||
*/
|
||||
export function updateStateInSupportForm(
|
||||
webview: WebviewTag,
|
||||
data: {[key: string]: any},
|
||||
) {
|
||||
webview.send('hostMessage', {
|
||||
type: 'updateState',
|
||||
payload: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param webview
|
||||
* This helper function returns the supported apps by NTUsersFormContainer.react.js
|
||||
*/
|
||||
export function supportedApps(webview: WebviewTag): Promise<Array<string>> {
|
||||
// TODO: Replace this with a promisified call to the guest page
|
||||
return injectJavaScript(
|
||||
webview,
|
||||
"Array.from(document.querySelector('ul[role=radiogroup]').children).map(e => e.getAttribute('data-value'))",
|
||||
);
|
||||
}
|
||||
18
static/SupportRequestPreload.js
Normal file
18
static/SupportRequestPreload.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
|
||||
const {ipcRenderer} = require('electron');
|
||||
|
||||
global.sendToHost = message => {
|
||||
ipcRenderer.sendToHost(message);
|
||||
};
|
||||
|
||||
global.setupToReceiveHostMessage = callback => {
|
||||
ipcRenderer.on('hostMessage', (event, message) => {
|
||||
callback(message);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user