Skip to content
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

feat: Agent Frontend #174

Merged
merged 14 commits into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module.exports = {
"@babel/preset-typescript"
],
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
"@babel/plugin-proposal-class-properties",
"@babel/transform-modules-commonjs"
"@babel/transform-modules-commonjs",
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
}
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/preset-typescript": "~7.3.3",
"@commitlint/cli": "^8.0.0",
"@commitlint/config-conventional": "^8.0.0",
Expand Down
17 changes: 17 additions & 0 deletions packages/@best/agent-frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["@salesforce/eslint-config-lwc/recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@lwc/lwc/no-async-operation": "warn",
"@lwc/lwc/no-inner-html": "warn",
"@lwc/lwc/no-document-query": "warn",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/no-explicit-any": "off"
},
"parserOptions": {
"ecmaVersion": 2018
}
}
1 change: 1 addition & 0 deletions packages/@best/agent-frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Aagent Frontend
12 changes: 12 additions & 0 deletions packages/@best/agent-frontend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const COMMON = require('../../../scripts/jest/common.config')

module.exports = {
...COMMON,
displayName: 'agent-frontend',
preset: '@lwc/jest-preset',
moduleNameMapper: {
"^component-emitter$": "component-emitter",
"^(component|my|view|store)(.+)$": "<rootDir>/src/modules/$1$2$2"
}
}
8 changes: 8 additions & 0 deletions packages/@best/agent-frontend/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"experimentalDecorators": true
},
"typeAcquisition": {
"include": ["jest"]
}
}
10 changes: 10 additions & 0 deletions packages/@best/agent-frontend/lwc-services.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Find the full example of all available configuration options at
// https://github.com/muenzpraeger/lwc-create-app/blob/master/packages/lwc-services/example/lwc-services.config.js
module.exports = {
resources: [{ from: 'src/client/resources', to: 'dist/resources' }],
sourceDir: './src/client',
moduleDir: './src/client/modules',
server: {
customConfig: './src/server/index.js'
}
};
36 changes: 36 additions & 0 deletions packages/@best/agent-frontend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@best/agent-frontend",
"version": "4.0.0",
"main": "build/index.js",
"dependencies": {
"@best/agent-logger": "4.0.0",
"express": "^4.17.1",
"lwc-services": "^1",
"socket.io-client": "~2.2.0",
"socket.io": "~2.2.0"
},
"devDependencies": {
"husky": "^2.3",
"lint-staged": "^8.1.5"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"**/modules/**/*.js": [
"eslint"
],
"*": [
"git add"
]
},
"scripts": {
"build": "lwc-services build -m production",
"build:development": "lwc-services build",
"lint": "eslint ./src/**/*.js",
"serve": "lwc-services serve",
"watch": "lwc-services watch"
}
}
21 changes: 21 additions & 0 deletions packages/@best/agent-frontend/src/client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Best Agent Dashboard</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
#main {
min-height: 65px;
padding-top: 50px;
}
</style>
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" href="/resources/favicon.ico">
</head>
<body>
<view-dashboard></view-dashboard>
</body>
</html>
4 changes: 4 additions & 0 deletions packages/@best/agent-frontend/src/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { buildCustomElementConstructor } from 'lwc';
import ViewDashboard from 'view/dashboard';

customElements.define('view-dashboard', buildCustomElementConstructor(ViewDashboard));
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<template>
<header>
<h2>{name}</h2>
</header>
<div class="jobs">
<template for:each={jobs} for:item="job">
<component-job key={job.jobId} job={job}></component-job>
</template>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { LightningElement, api } from 'lwc';

export default class ComponentAgent extends LightningElement {
@api jobs = [];
@api name = '';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.job {
margin: 10px 0;
}

.status {
border-radius: 4px 4px 0 0;
display: block;
padding: 4px 8px;
font-size: 80%;
margin-right: 0;
z-index: 1;
}

.status.added, .status.queued { background: #cccccc; color: #252525; }
.status.running { background: #adcff0; color: #032546; }
.status.completed { background: #a0dfb5; color: #063b18; }
.status.cancelled { background: #ebcd8c; color: #614700; }
.status.error { background: #eb8c8c; color: #610000; }

main {
display: grid;
grid-template-columns: auto 200px;
background: #eee;
padding: 12px;
border-radius: 0 0 4px 4px;
}

.info {
display: flex;
flex-direction: row;
align-items: center;
}

.info h2 {
display: inline-block;
margin: 0;
font-weight: normal;
}

.stats {
text-align: right;
}

.stats p {
margin: 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<div class="job">
<span class={statusClass}>{job.status}</span>
<main>
<div class="info">
<h2 class="name">{job.name}</h2>
</div>
<div class="stats">
<template if:true={isRunning}>
<progress value={job.progressValue} max="100"></progress>
<template if:true={hasEstimate}>
<span class="estimate">{estimatedText}</span>
</template>
</template>
<template if:true={isCompleted}>
<p>{statsText}</p>
</template>
</div>
</main>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { LightningElement, api } from 'lwc';

export default class ComponentJob extends LightningElement {
@api job = {};

get statusClass() {
return 'status ' + this.job.status.toLowerCase();
}

get isRunning() {
return this.job.status === 'RUNNING';
}

get isCompleted() {
return this.job.status === 'COMPLETED';
}

get statsText() {
const { time, completedIterations } = this.job;

return `N: ${completedIterations}, T: ${time}s`;
}

get hasEstimate() {
return !!this.job.estimatedTime;
}

get estimatedText() {
const { estimatedTime } = this.job;

return `${estimatedTime}s`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export class Job {
agentId;
jobId;
name;
status = 'ADDED';

constructor(jobId, name) {
this.jobId = jobId;
this.name = name;
}

get progressValue() {
if (this._time && this._estimatedTime) {
return (this._time / this.estimatedTime) * 100;
}

return 0;
}

_estimatedTime;
get estimatedTime() {
return this._estimatedTime;
}

_completedIterations;
get completedIterations() {
return this._completedIterations;
}

_time;
get time() {
return this._time;
}

update({ state, opts }) {
const { executedIterations, executedTime } = state;
const { iterations, maxDuration } = opts;
const avgIteration = executedTime / executedIterations;
const runtime = parseInt((executedTime / 1000) + '', 10);
const estimated = iterations ? Math.round(iterations * avgIteration / 1000) + 1 : maxDuration / 1000;

this._time = runtime;
this._estimatedTime = estimated;
}

results(count) {
this.status = 'COMPLETED';
this._completedIterations = count;
}

objectified() {
const { agentId, jobId, name, status, progressValue, estimatedTime, completedIterations, time } = this;
return { agentId, jobId, name, status, progressValue, estimatedTime, completedIterations, time };
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import io from 'socket.io-client';

export const connect = (...args) => {
return io.connect(...args);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.container {
width: 800px;
margin: 40px auto;
}

header {
box-sizing: border-box;
}

.no-jobs {
text-align: center;
background: rgb(255, 249, 199);
border-radius: 4px;
padding: 8px 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div class="container">
<template for:each={agents} for:item="agent">
<component-agent key={agent.agentId} name={agent.agentId} jobs={agent.jobs}></component-agent>
</template>

<template if:false={hasJobs}>
<div class="no-jobs">
<p>There are no jobs currently running.</p>
</div>
</template>
</div>
</template>
Loading