Skip to content

Commit

Permalink
Merge branch 'actions/license-checks' into actions/initial-action-typ…
Browse files Browse the repository at this point in the history
…e-licenses
  • Loading branch information
elasticmachine authored Mar 2, 2020
2 parents b6d5c0e + a3be4e2 commit af432ef
Show file tree
Hide file tree
Showing 531 changed files with 63,710 additions and 20,427 deletions.
9 changes: 7 additions & 2 deletions examples/ui_action_examples/public/hello_world_action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ import { toMountPoint } from '../../../src/plugins/kibana_react/public';

export const HELLO_WORLD_ACTION_TYPE = 'HELLO_WORLD_ACTION_TYPE';

export const createHelloWorldAction = (openModal: OverlayStart['openModal']) =>
createAction<{}>({
interface StartServices {
openModal: OverlayStart['openModal'];
}

export const createHelloWorldAction = (getStartServices: () => Promise<StartServices>) =>
createAction({
type: HELLO_WORLD_ACTION_TYPE,
getDisplayName: () => 'Hello World!',
execute: async () => {
const { openModal } = await getStartServices();
const overlay = openModal(
toMountPoint(
<EuiModalBody>
Expand Down
28 changes: 16 additions & 12 deletions examples/ui_action_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,34 @@
* under the License.
*/

import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public';
import { UiActionsSetup, UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { createHelloWorldAction, HELLO_WORLD_ACTION_TYPE } from './hello_world_action';
import { helloWorldTrigger } from './hello_world_trigger';
import { Plugin, CoreSetup } from '../../../src/core/public';
import { UiActionsSetup } from '../../../src/plugins/ui_actions/public';
import { createHelloWorldAction } from './hello_world_action';
import { helloWorldTrigger, HELLO_WORLD_TRIGGER_ID } from './hello_world_trigger';

interface UiActionExamplesSetupDependencies {
uiActions: UiActionsSetup;
}

interface UiActionExamplesStartDependencies {
uiActions: UiActionsStart;
declare module '../../../src/plugins/ui_actions/public' {
export interface TriggerContextMapping {
[HELLO_WORLD_TRIGGER_ID]: undefined;
}
}

export class UiActionExamplesPlugin
implements
Plugin<void, void, UiActionExamplesSetupDependencies, UiActionExamplesStartDependencies> {
implements Plugin<void, void, UiActionExamplesSetupDependencies> {
public setup(core: CoreSetup, { uiActions }: UiActionExamplesSetupDependencies) {
uiActions.registerTrigger(helloWorldTrigger);
uiActions.attachAction(helloWorldTrigger.id, HELLO_WORLD_ACTION_TYPE);
}

public start(coreStart: CoreStart, deps: UiActionExamplesStartDependencies) {
deps.uiActions.registerAction(createHelloWorldAction(coreStart.overlays.openModal));
const helloWorldAction = createHelloWorldAction(async () => ({
openModal: (await core.getStartServices())[0].overlays.openModal,
}));

uiActions.registerAction(helloWorldAction);
uiActions.attachAction(helloWorldTrigger.id, helloWorldAction.id);
}

public start() {}
public stop() {}
}
30 changes: 19 additions & 11 deletions examples/ui_actions_explorer/public/actions/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ export const EDIT_USER_ACTION = 'EDIT_USER_ACTION';
export const PHONE_USER_ACTION = 'PHONE_USER_ACTION';
export const SHOWCASE_PLUGGABILITY_ACTION = 'SHOWCASE_PLUGGABILITY_ACTION';

export const showcasePluggability = createAction<{}>({
export const showcasePluggability = createAction({
type: SHOWCASE_PLUGGABILITY_ACTION,
getDisplayName: () => 'This is pluggable! Any plugin can inject their actions here.',
execute: async ({}) => alert("Isn't that cool?!"),
execute: async () => alert("Isn't that cool?!"),
});

export const makePhoneCallAction = createAction<{ phone: string }>({
export type PhoneContext = string;

export const makePhoneCallAction = createAction<PhoneContext>({
type: CALL_PHONE_NUMBER_ACTION,
getDisplayName: () => 'Call phone number',
execute: async ({ phone }) => alert(`Pretend calling ${phone}...`),
execute: async phone => alert(`Pretend calling ${phone}...`),
});

export const lookUpWeatherAction = createAction<{ country: string }>({
Expand All @@ -55,11 +57,13 @@ export const lookUpWeatherAction = createAction<{ country: string }>({
},
});

export const viewInMapsAction = createAction<{ country: string }>({
export type CountryContext = string;

export const viewInMapsAction = createAction<CountryContext>({
type: VIEW_IN_MAPS_ACTION,
getIconType: () => 'popout',
getDisplayName: () => 'View in maps',
execute: async ({ country }) => {
execute: async country => {
window.open(`https://www.google.com/maps/place/${country}`, '_blank');
},
});
Expand Down Expand Up @@ -110,11 +114,13 @@ export const createEditUserAction = (getOpenModal: () => Promise<OverlayStart['o
},
});

export interface UserContext {
user: User;
update: (user: User) => void;
}

export const createPhoneUserAction = (getUiActionsApi: () => Promise<UiActionsStart>) =>
createAction<{
user: User;
update: (user: User) => void;
}>({
createAction<UserContext>({
type: PHONE_USER_ACTION,
getDisplayName: () => 'Call phone number',
isCompatible: async ({ user }) => user.phone !== undefined,
Expand All @@ -126,6 +132,8 @@ export const createPhoneUserAction = (getUiActionsApi: () => Promise<UiActionsSt
// to the phone number trigger.
// TODO: we need to figure out the best way to handle these nested actions however, since
// we don't want multiple context menu's to pop up.
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, { phone: user.phone });
if (user.phone !== undefined) {
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, user.phone);
}
},
});
2 changes: 1 addition & 1 deletion examples/ui_actions_explorer/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => {
</EuiText>
<EuiButton
data-test-subj="emitHelloWorldTrigger"
onClick={() => uiActionsApi.executeTriggerActions(HELLO_WORLD_TRIGGER_ID, {})}
onClick={() => uiActionsApi.executeTriggerActions(HELLO_WORLD_TRIGGER_ID, undefined)}
>
Say hello world!
</EuiButton>
Expand Down
11 changes: 11 additions & 0 deletions examples/ui_actions_explorer/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import {
makePhoneCallAction,
showcasePluggability,
SHOWCASE_PLUGGABILITY_ACTION,
UserContext,
CountryContext,
PhoneContext,
} from './actions/actions';

interface StartDeps {
Expand All @@ -45,6 +48,14 @@ interface SetupDeps {
uiActions: UiActionsSetup;
}

declare module '../../../src/plugins/ui_actions/public' {
export interface TriggerContextMapping {
[USER_TRIGGER]: UserContext;
[COUNTRY_TRIGGER]: CountryContext;
[PHONE_TRIGGER]: PhoneContext;
}
}

export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps> {
public setup(core: CoreSetup<{ uiActions: UiActionsStart }>, deps: SetupDeps) {
deps.uiActions.registerTrigger({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ const createRowData = (
<Fragment>
<EuiButtonEmpty
onClick={() => {
uiActionsApi.executeTriggerActions(COUNTRY_TRIGGER, {
country: user.countryOfResidence,
});
uiActionsApi.executeTriggerActions(COUNTRY_TRIGGER, user.countryOfResidence);
}}
>
{user.countryOfResidence}
Expand All @@ -59,10 +57,9 @@ const createRowData = (
phone: (
<Fragment>
<EuiButtonEmpty
disabled={user.phone === undefined}
onClick={() => {
uiActionsApi.executeTriggerActions(PHONE_TRIGGER, {
phone: user.phone,
});
uiActionsApi.executeTriggerActions(PHONE_TRIGGER, user.phone!);
}}
>
{user.phone}
Expand Down
17 changes: 5 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,31 +77,23 @@
"url": "https://github.com/elastic/kibana.git"
},
"resolutions": {
"**/@apollo/client": "^3.0.0-beta.37",
"**/@graphql-toolkit/common": "^0.9.7",
"**/@graphql-toolkit/core": "^0.9.7",
"**/@graphql-toolkit/graphql-file-loader": "^0.9.7",
"**/@graphql-toolkit/json-file-loader": "^0.9.7",
"**/@graphql-toolkit/schema-merging": "^0.9.7",
"**/@graphql-toolkit/url-loader": "^0.9.7",
"**/@types/node": "10.12.27",
"**/@types/react": "^16.9.19",
"**/@types/react-router": "^5.1.3",
"**/@types/hapi": "^17.0.18",
"**/@types/angular": "^1.6.56",
"**/@types/hoist-non-react-statics": "^3.3.1",
"**/apollo-link": "^1.2.13",
"**/deepmerge": "^4.2.2",
"**/fast-deep-equal": "^3.1.1",
"**/fast-glob": "3.1.1",
"**/typescript": "3.7.2",
"**/graphql-toolkit/lodash": "^4.17.13",
"**/hoist-non-react-statics": "^3.3.2",
"**/isomorphic-git/**/base64-js": "^1.2.1",
"**/image-diff/gm/debug": "^2.6.9",
"**/react-dom": "^16.12.0",
"**/react": "^16.12.0",
"**/react-test-renderer": "^16.12.0",
"**/deepmerge": "^4.2.2",
"**/serialize-javascript": "^2.1.1",
"**/typescript": "3.7.2"
"**/fast-deep-equal": "^3.1.1"
},
"workspaces": {
"packages": [
Expand Down Expand Up @@ -333,6 +325,7 @@
"@types/getopts": "^2.0.1",
"@types/glob": "^7.1.1",
"@types/globby": "^8.0.0",
"@types/graphql": "^0.13.2",
"@types/hapi": "^17.0.18",
"@types/hapi-auth-cookie": "^9.1.0",
"@types/has-ansi": "^3.0.0",
Expand Down
56 changes: 56 additions & 0 deletions packages/kbn-analytics/src/metrics/application_usage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import moment, { Moment } from 'moment-timezone';
import { METRIC_TYPE } from './';

export interface ApplicationUsageCurrent {
type: METRIC_TYPE.APPLICATION_USAGE;
appId: string;
startTime: Moment;
numberOfClicks: number;
}

export class ApplicationUsage {
private currentUsage?: ApplicationUsageCurrent;

public start() {
// Count any clicks and assign it to the current app
if (window)
window.addEventListener(
'click',
() => this.currentUsage && this.currentUsage.numberOfClicks++
);
}

public appChanged(appId?: string) {
const currentUsage = this.currentUsage;

if (appId) {
this.currentUsage = {
type: METRIC_TYPE.APPLICATION_USAGE,
appId,
startTime: moment(),
numberOfClicks: 0,
};
} else {
this.currentUsage = void 0;
}
return currentUsage;
}
}
5 changes: 4 additions & 1 deletion packages/kbn-analytics/src/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@

import { UiStatsMetric } from './ui_stats';
import { UserAgentMetric } from './user_agent';
import { ApplicationUsageCurrent } from './application_usage';

export { UiStatsMetric, createUiStatsMetric, UiStatsMetricType } from './ui_stats';
export { Stats } from './stats';
export { trackUsageAgent } from './user_agent';
export { ApplicationUsage, ApplicationUsageCurrent } from './application_usage';

export type Metric = UiStatsMetric | UserAgentMetric;
export type Metric = UiStatsMetric | UserAgentMetric | ApplicationUsageCurrent;
export enum METRIC_TYPE {
COUNT = 'count',
LOADED = 'loaded',
CLICK = 'click',
USER_AGENT = 'user_agent',
APPLICATION_USAGE = 'application_usage',
}
29 changes: 27 additions & 2 deletions packages/kbn-analytics/src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import moment from 'moment-timezone';
import { UnreachableCaseError, wrapArray } from './util';
import { Metric, Stats, UiStatsMetricType, METRIC_TYPE } from './metrics';
const REPORT_VERSION = 1;
Expand All @@ -42,6 +43,13 @@ export interface Report {
appName: string;
}
>;
application_usage?: Record<
string,
{
minutesOnScreen: number;
numberOfClicks: number;
}
>;
}

export class ReportManager {
Expand All @@ -57,10 +65,11 @@ export class ReportManager {
this.report = ReportManager.createReport();
}
public isReportEmpty(): boolean {
const { uiStatsMetrics, userAgent } = this.report;
const { uiStatsMetrics, userAgent, application_usage: appUsage } = this.report;
const noUiStats = !uiStatsMetrics || Object.keys(uiStatsMetrics).length === 0;
const noUserAgent = !userAgent || Object.keys(userAgent).length === 0;
return noUiStats && noUserAgent;
const noAppUsage = !appUsage || Object.keys(appUsage).length === 0;
return noUiStats && noUserAgent && noAppUsage;
}
private incrementStats(count: number, stats?: Stats): Stats {
const { min = 0, max = 0, sum = 0 } = stats || {};
Expand Down Expand Up @@ -92,6 +101,8 @@ export class ReportManager {
const { appName, eventName, type } = metric;
return `${appName}-${type}-${eventName}`;
}
case METRIC_TYPE.APPLICATION_USAGE:
return metric.appId;
default:
throw new UnreachableCaseError(metric);
}
Expand Down Expand Up @@ -129,6 +140,20 @@ export class ReportManager {
};
return;
}
case METRIC_TYPE.APPLICATION_USAGE:
const { numberOfClicks, startTime } = metric;
const minutesOnScreen = moment().diff(startTime, 'minutes', true);

report.application_usage = report.application_usage || {};
const appExistingData = report.application_usage[key] || {
minutesOnScreen: 0,
numberOfClicks: 0,
};
report.application_usage[key] = {
minutesOnScreen: appExistingData.minutesOnScreen + minutesOnScreen,
numberOfClicks: appExistingData.numberOfClicks + numberOfClicks,
};
break;
default:
throw new UnreachableCaseError(metric);
}
Expand Down
Loading

0 comments on commit af432ef

Please sign in to comment.