-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Beats/initial ui #20994
Beats/initial ui #20994
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
import { EuiPage, EuiPageBody, EuiPageContent, EuiPageContentBody, EuiTitle } from '@elastic/eui'; | ||
|
||
interface PrimaryLayoutProps { | ||
title: string; | ||
actionSection: React.ReactNode; | ||
} | ||
|
||
const HeaderContainer = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: flex-start; | ||
padding: 24px 24px 0; | ||
margin-bottom: 16px; | ||
`; | ||
|
||
export const PrimaryLayout: React.SFC<PrimaryLayoutProps> = ({ | ||
actionSection, | ||
title, | ||
children, | ||
}) => ( | ||
<EuiPage> | ||
<EuiPageBody> | ||
<EuiPageContent> | ||
<HeaderContainer> | ||
<EuiTitle> | ||
<h1>{title}</h1> | ||
</EuiTitle> | ||
{actionSection} | ||
</HeaderContainer> | ||
<EuiPageContentBody>{children}</EuiPageContentBody> | ||
</EuiPageContent> | ||
</EuiPageBody> | ||
</EuiPage> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { CMBeat } from '../../../../common/domain_types'; | ||
|
||
export interface CMBeatsAdapter { | ||
get(id: string): Promise<CMBeat | null>; | ||
getAll(): Promise<CMBeat[]>; | ||
getWithIds(beatIds: string[]): Promise<CMBeat[]>; | ||
removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise<BeatsTagAssignment[]>; | ||
assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise<BeatsTagAssignment[]>; | ||
} | ||
|
||
export interface BeatsTagAssignment { | ||
beatId: string; | ||
tag: string; | ||
idxInRequest?: number; | ||
} | ||
|
||
interface BeatsReturnedTagAssignment { | ||
status: number | null; | ||
result?: string; | ||
} | ||
|
||
export interface CMAssignmentReturn { | ||
assignments: BeatsReturnedTagAssignment[]; | ||
} | ||
|
||
export interface BeatsRemovalReturn { | ||
removals: BeatsReturnedTagAssignment[]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { omit } from 'lodash'; | ||
|
||
import { CMBeat } from '../../../../common/domain_types'; | ||
import { BeatsTagAssignment, CMBeatsAdapter } from './adapter_types'; | ||
|
||
export class MemoryBeatsAdapter implements CMBeatsAdapter { | ||
private beatsDB: CMBeat[]; | ||
|
||
constructor(beatsDB: CMBeat[]) { | ||
this.beatsDB = beatsDB; | ||
} | ||
|
||
public async get(id: string) { | ||
return this.beatsDB.find(beat => beat.id === id) || null; | ||
} | ||
|
||
public async getWithIds(beatIds: string[]) { | ||
return this.beatsDB.filter(beat => beatIds.includes(beat.id)); | ||
} | ||
|
||
public async getAll() { | ||
return this.beatsDB.map<CMBeat>((beat: any) => omit(beat, ['access_token'])); | ||
} | ||
|
||
public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise<BeatsTagAssignment[]> { | ||
const beatIds = removals.map(r => r.beatId); | ||
|
||
const response = this.beatsDB.filter(beat => beatIds.includes(beat.id)).map(beat => { | ||
const tagData = removals.find(r => r.beatId === beat.id); | ||
if (tagData) { | ||
if (beat.tags) { | ||
beat.tags = beat.tags.filter(tag => tag !== tagData.tag); | ||
} | ||
} | ||
return beat; | ||
}); | ||
|
||
return response.map<any>((item: CMBeat, resultIdx: number) => ({ | ||
idxInRequest: removals[resultIdx].idxInRequest, | ||
result: 'updated', | ||
status: 200, | ||
})); | ||
} | ||
|
||
public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise<BeatsTagAssignment[]> { | ||
const beatIds = assignments.map(r => r.beatId); | ||
|
||
this.beatsDB.filter(beat => beatIds.includes(beat.id)).map(beat => { | ||
// get tags that need to be assigned to this beat | ||
const tags = assignments | ||
.filter(a => a.beatId === beat.id) | ||
.map((t: BeatsTagAssignment) => t.tag); | ||
|
||
if (tags.length > 0) { | ||
if (!beat.tags) { | ||
beat.tags = []; | ||
} | ||
const nonExistingTags = tags.filter((t: string) => beat.tags && !beat.tags.includes(t)); | ||
|
||
if (nonExistingTags.length > 0) { | ||
beat.tags = beat.tags.concat(nonExistingTags); | ||
} | ||
} | ||
return beat; | ||
}); | ||
|
||
return assignments.map<any>((item: BeatsTagAssignment, resultIdx: number) => ({ | ||
idxInRequest: assignments[resultIdx].idxInRequest, | ||
result: 'updated', | ||
status: 200, | ||
})); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
import { BeatTag } from '../../../../common/domain_types'; | ||
|
||
export interface CMTagsAdapter { | ||
getTagsWithIds(tagIds: string[]): Promise<BeatTag[]>; | ||
upsertTag(tag: BeatTag): Promise<{}>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a general TypeScript question, what's the difference between returning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Promise<{}> is saying its returning an object with unknown keys, any could be anything. It's an only slightly more precise placeholder for now |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { BeatTag } from '../../../../common/domain_types'; | ||
import { CMTagsAdapter } from './adapter_types'; | ||
|
||
export class MemoryTagsAdapter implements CMTagsAdapter { | ||
private tagsDB: BeatTag[] = []; | ||
|
||
constructor(tagsDB: BeatTag[]) { | ||
this.tagsDB = tagsDB; | ||
} | ||
|
||
public async getTagsWithIds(tagIds: string[]) { | ||
return this.tagsDB.filter(tag => tagIds.includes(tag.id)); | ||
} | ||
|
||
public async upsertTag(tag: BeatTag) { | ||
const existingTagIndex = this.tagsDB.findIndex(t => t.id === tag.id); | ||
if (existingTagIndex !== -1) { | ||
this.tagsDB[existingTagIndex] = tag; | ||
} else { | ||
this.tagsDB.push(tag); | ||
} | ||
return tag; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
export interface TokenEnrollmentData { | ||
token: string | null; | ||
expires_on: string; | ||
} | ||
|
||
export interface CMTokensAdapter { | ||
createEnrollmentToken(): Promise<TokenEnrollmentData>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { CMTokensAdapter, TokenEnrollmentData } from './adapter_types'; | ||
|
||
export class MemoryTokensAdapter implements CMTokensAdapter { | ||
public async createEnrollmentToken(): Promise<TokenEnrollmentData> { | ||
return { | ||
token: '2jnwkrhkwuehriauhweair', | ||
expires_on: new Date().toJSON(), | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import 'ui/autoload/all'; | ||
// @ts-ignore: path dynamic for kibana | ||
import { management } from 'ui/management'; | ||
// @ts-ignore: path dynamic for kibana | ||
import { uiModules } from 'ui/modules'; | ||
// @ts-ignore: path dynamic for kibana | ||
import routes from 'ui/routes'; | ||
// @ts-ignore: path dynamic for kibana | ||
import { MemoryBeatsAdapter } from '../adapters/beats/memory_beats_adapter'; | ||
import { KibanaFrameworkAdapter } from '../adapters/framework/kibana_framework_adapter'; | ||
import { MemoryTagsAdapter } from '../adapters/tags/memory_tags_adapter'; | ||
import { MemoryTokensAdapter } from '../adapters/tokens/memory_tokens_adapter'; | ||
|
||
import { FrontendDomainLibs, FrontendLibs } from '../lib'; | ||
|
||
export function compose(): FrontendLibs { | ||
const tags = new MemoryTagsAdapter([]); | ||
const tokens = new MemoryTokensAdapter(); | ||
const beats = new MemoryBeatsAdapter([]); | ||
|
||
const domainLibs: FrontendDomainLibs = { | ||
tags, | ||
tokens, | ||
beats, | ||
}; | ||
const pluginUIModule = uiModules.get('app/beats_management'); | ||
|
||
const framework = new KibanaFrameworkAdapter(pluginUIModule, management, routes); | ||
const libs: FrontendLibs = { | ||
...domainLibs, | ||
framework, | ||
}; | ||
return libs; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
export class ActivityPage extends React.PureComponent { | ||
public render() { | ||
return <div>activity logs view</div>; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have defined
CMPopulatedBeat
on my Beats List branch; I assume we will add methods for getting that data here as well?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, the beats adapter will have additional methods for managing this