Merge pull request #2144 from weaveworks/2133-scope-component

Allow Scope UI to be installed as a Node module
This commit is contained in:
Jordan Pellizzari
2017-01-24 15:48:19 -08:00
committed by GitHub
12 changed files with 77 additions and 69 deletions

1
.gitignore vendored
View File

@@ -56,3 +56,4 @@ vendor/github.com/ugorji/go/codec/codecgen/bin/*
client/build-external/*
prog/staticui/*
prog/externalui/*
client/pkg

View File

@@ -167,6 +167,9 @@ ui-upload: client/build-external/index.html
AWS_SECRET_ACCESS_KEY=$$UI_BUCKET_KEY_SECRET \
aws s3 cp client/build-external/ s3://static.weave.works/scope-ui/ --recursive --exclude '*.html'
ui-build-pkg:
cd client && npm run build-pkg && npm run s3-publish
clean:
$(GO) clean ./...
# Don't actually rmi the build images - rm'ing the .uptodate files is enough to ensure

View File

@@ -75,7 +75,8 @@ deployment:
)) &&
docker push ${DOCKER_ORGANIZATION:-$DOCKER_USER}/scope &&
docker push ${DOCKER_ORGANIZATION:-$DOCKER_USER}/scope:$(./tools/image-tag) &&
(test -z "${UI_BUCKET_KEY_ID}" || make ui-upload)
(test -z "${UI_BUCKET_KEY_ID}" || make ui-upload) &&
make ui-build-pkg
)
- |
test -z "${QUAY_USER}" || (

View File

@@ -1,5 +1,6 @@
{
"extends": "airbnb",
"parser": "babel-eslint",
"env": {
"browser": true,
"jest": true,

1
client/.gitignore vendored
View File

@@ -2,3 +2,4 @@ node_modules
build/
coverage/
test/*png
weave-scope.tgz

View File

@@ -104,7 +104,7 @@ class App extends React.Component {
const isIframe = window !== window.top;
return (
<div className="app">
<div className="scope-app">
{showingDebugToolbar() && <DebugToolbar />}
{showingHelp && <HelpPanel />}

View File

@@ -9,10 +9,8 @@ import Term from 'xterm';
import { clickCloseTerminal } from '../actions/app-actions';
import { getNeutralColor } from '../utils/color-utils';
import { setDocumentTitle } from '../utils/title-utils';
import { getPipeStatus, basePath, doResizeTty } from '../utils/web-api-utils';
import { getPipeStatus, doResizeTty, wsUrl } from '../utils/web-api-utils';
const wsProto = location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${wsProto}://${location.host}${basePath(location.pathname)}`;
const log = debug('scope:terminal');
const DEFAULT_COLS = 80;

View File

@@ -1,5 +1,5 @@
const PREFIX = 'Weave Scope';
const PREFIX = document.title || 'Weave Scope';
const SEPARATOR = ' - ';
export function setDocumentTitle(title) {

View File

@@ -58,8 +58,14 @@ export function basePathSlash(urlPath) {
return `${basePath(urlPath)}/`;
}
const API_PATH = basePathSlash(window.location.pathname) === '/'
? 'api'
: `/api${window.location.pathname}/api`;
const wsProto = location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${wsProto}://${location.host}${basePath(location.pathname)}`;
export const wsUrl = basePathSlash(window.location.pathname) === '/'
? `${wsProto}://${location.host}${basePath(window.location.pathname)}`
: `${wsProto}://${location.host}/api${basePath(window.location.pathname)}`;
function createWebsocket(topologyUrl, optionsQuery, dispatch) {
if (socket) {
@@ -136,7 +142,7 @@ export function getAllNodes(getState, dispatch) {
export function getTopologies(options, dispatch) {
clearTimeout(topologyTimer);
const optionsQuery = buildOptionsQuery(options);
const url = `api/topology?${optionsQuery}`;
const url = `${API_PATH}/topology?${optionsQuery}`;
reqwest({
url,
success: (res) => {
@@ -171,13 +177,13 @@ export function getNodeDetails(topologyUrlsById, currentTopologyId, options, nod
const obj = nodeMap.last();
if (obj && topologyUrlsById.has(obj.topologyId)) {
const topologyUrl = topologyUrlsById.get(obj.topologyId);
let urlComponents = [topologyUrl, '/', encodeURIComponent(obj.id)];
let urlComponents = [API_PATH, '/', trimStart(topologyUrl, '/api'), '/', encodeURIComponent(obj.id)];
if (currentTopologyId === obj.topologyId) {
// Only forward filters for nodes in the current topology
const optionsQuery = buildOptionsQuery(options);
urlComponents = urlComponents.concat(['?', optionsQuery]);
}
const url = urlComponents.join('').substr(1);
const url = urlComponents.join('');
reqwest({
url,
@@ -204,7 +210,7 @@ export function getNodeDetails(topologyUrlsById, currentTopologyId, options, nod
export function getApiDetails(dispatch) {
clearTimeout(apiDetailsTimer);
const url = 'api';
const url = API_PATH;
reqwest({
url,
success: (res) => {
@@ -225,7 +231,7 @@ export function getApiDetails(dispatch) {
export function doControlRequest(nodeId, control, dispatch) {
clearTimeout(controlErrorTimer);
const url = `api/control/${encodeURIComponent(control.probeId)}/`
const url = `${API_PATH}/control/${encodeURIComponent(control.probeId)}/`
+ `${encodeURIComponent(control.nodeId)}/${control.id}`;
reqwest({
method: 'POST',
@@ -261,7 +267,7 @@ export function doControlRequest(nodeId, control, dispatch) {
export function doResizeTty(pipeId, control, cols, rows) {
const url = `api/control/${encodeURIComponent(control.probeId)}/`
const url = `${API_PATH}/control/${encodeURIComponent(control.probeId)}/`
+ `${encodeURIComponent(control.nodeId)}/${control.id}`;
return reqwest({
@@ -276,7 +282,7 @@ export function doResizeTty(pipeId, control, cols, rows) {
export function deletePipe(pipeId, dispatch) {
const url = `api/pipe/${encodeURIComponent(pipeId)}`;
const url = `${API_PATH}/pipe/${encodeURIComponent(pipeId)}`;
reqwest({
method: 'DELETE',
url,
@@ -292,7 +298,7 @@ export function deletePipe(pipeId, dispatch) {
export function getPipeStatus(pipeId, dispatch) {
const url = `api/pipe/${encodeURIComponent(pipeId)}/check`;
const url = `${API_PATH}/pipe/${encodeURIComponent(pipeId)}/check`;
reqwest({
method: 'GET',
url,

View File

@@ -115,63 +115,52 @@ $label-background-color: fade-out($background-average-color, .3);
}
}
* {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
*:before,
*:after {
box-sizing: border-box;
}
html {
-webkit-font-smoothing: antialiased;
}
html,
body {
height: 100%;
width: 100%;
}
/* Space out content a bit */
body {
background: $body-background-color;
color: $text-color;
line-height: 150%;
font-family: $base-font;
font-size: 13px;
margin: 0;
}
p {
line-height: 20px;
padding-top: 6px;
margin-bottom: 14px;
letter-spacing: 0;
font-weight: 400;
color: $text-color;
}
h2 {
font-size: 34px;
line-height: 40px;
padding-top: 8px;
margin-bottom: 12px;
font-weight: 400;
}
.hide {
opacity: 0;
}
.app {
position: fixed;
top: 0;
left: 0;
.scope-app {
-webkit-font-smoothing: antialiased;
background: $body-background-color;
bottom: 0;
right: 0;
color: $text-color;
font-family: $base-font;
font-size: 13px;
height: 100%;
left: 0;
line-height: 150%;
margin: 0;
overflow: auto;
position: fixed;
right: 0;
top: 0;
width: 100%;
* {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
*:before,
*:after {
box-sizing: border-box;
}
p {
line-height: 20px;
padding-top: 6px;
margin-bottom: 14px;
letter-spacing: 0;
font-weight: 400;
color: $text-color;
}
h2 {
font-size: 34px;
line-height: 40px;
padding-top: 8px;
margin-bottom: 12px;
font-weight: 400;
}
}
.header {

3
client/index.js Normal file
View File

@@ -0,0 +1,3 @@
exports.reducer = require('./dist/reducers/root').default;
exports.Scope = require('./dist/components/app').default;
exports.ActionTypes = require('./dist/constants/action-types').default;

View File

@@ -5,7 +5,9 @@
"repository": "weaveworks/scope",
"license": "Apache-2.0",
"private": true,
"main": "index.js",
"dependencies": {
"babel-plugin-lodash": "^3.2.10",
"babel-polyfill": "6.16.0",
"classnames": "2.2.5",
"d3-array": "1.0.2",
@@ -39,15 +41,16 @@
"reselect": "2.5.4",
"timely": "0.1.0",
"whatwg-fetch": "2.0.1",
"react-addons-perf": "15.4.1",
"xterm": "2.1.0"
},
"devDependencies": {
"autoprefixer": "6.5.3",
"babel-cli": "^6.18.0",
"babel-core": "6.18.2",
"babel-eslint": "7.1.1",
"babel-jest": "17.0.2",
"babel-loader": "6.2.8",
"babel-plugin-lodash": "3.2.10",
"babel-preset-es2015": "6.18.0",
"babel-preset-react": "6.16.0",
"clean-webpack-plugin": "0.1.14",
@@ -67,7 +70,6 @@
"json-loader": "0.5.4",
"node-sass": "3.13.1",
"postcss-loader": "1.2.0",
"react-addons-perf": "15.4.1",
"redux-devtools": "3.3.1",
"redux-devtools-dock-monitor": "1.1.1",
"redux-devtools-log-monitor": "1.1.1",
@@ -88,6 +90,8 @@
"scripts": {
"build": "webpack --config webpack.production.config.js",
"build-external": "EXTERNAL=true webpack --config webpack.production.config.js",
"build-pkg": "babel app/scripts --ignore __tests__ --out-dir pkg && cp package.json pkg/ && cp -R app/styles pkg/",
"bundle": "npm pack pkg && mv weave-scope-$npm_package_version.tgz weave-scope.tgz",
"start": "node server.js",
"start-production": "NODE_ENV=production node server.js",
"test": "jest",
@@ -95,7 +99,8 @@
"lint": "eslint app",
"clean": "rm build/app.js",
"noprobe": "../scope stop && ../scope launch --no-probe --app.window 8760h",
"loadreport": "npm run noprobe && sleep 1 && curl -X POST -H \"Content-Type: application/json\" http://$BACKEND_HOST/api/report -d"
"loadreport": "npm run noprobe && sleep 1 && curl -X POST -H \"Content-Type: application/json\" http://$BACKEND_HOST/api/report -d",
"s3-publish": "aws s3 cp weave-scope.tgz s3://weaveworks-npm-modules/weave-scope/ --acl public-read"
},
"jest": {
"transform": {