Skip to content
This repository has been archived by the owner on Oct 26, 2021. It is now read-only.

Track and show individual subscriptions to input streams #38

Closed
Closed
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: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015"]
}
1 change: 1 addition & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ DONE Fix marble hover and dragging styles for Firefox
DONE Fix affordance animation stuck for combineLatest
>>> v1.4.0

DONE Track and show individual subscriptions to input streams
TODO Fix visual semantics of concat diagram
>>>

Expand Down
4 changes: 2 additions & 2 deletions dist/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@
}
body {
position: relative;
background: #ececec;
background: #ECECEC;
font-family: 'Source Sans Pro', sans-serif;
color: #323232;
}
a {
color: #3ea1cb;
color: #3EA1CB;
}
p.marbleContent {
-webkit-user-select: none;
Expand Down
24,727 changes: 24,711 additions & 16 deletions dist/js/app.js

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@
"@cycle/core": "1.0.x",
"@cycle/dom": "3.1.x",
"immutable": "^3.7.2",
"rxtween": "0.3.3"
"rx": "^2.5.3",
"rxtween": "^0.3.3"
},
"devDependencies": {
"babel": "^5.2.7",
"babel-cli": "^6.14.0",
"babel-preset-es2015": "^6.14.0",
"browserify": "10.1.3",
"less": "^2.5.0",
"uglify-js": "~2.4.21",
"watchify": "~3.2.1",
"babel": "^5.2.7"
"watchify": "~3.2.1"
},
"scripts": {
"preinstall": "rm -rf build && rm -rf node_modules && mkdir -p ignore/es5src",
"postinstall": "ln -s ../ignore/es5src node_modules/rxmarbles && ln -s ../package.json node_modules/package.json",
"preinstall": "rm -rf build && rm -rf node_modules && mkdir -p ignore/es5src && rm -f node_modules/rxmarbles node_modules/package.json ignore/es5src/node_modules",
"postinstall": "ln -s ../ignore/es5src node_modules/rxmarbles && ln -s ../package.json node_modules/package.json && ln -s ../../node_modules ignore/es5src/node_modules",
"less": "lessc styles/main.less dist/css/main.css",
"babel": "mkdir -p ignore/es5src && babel src --out-dir ignore/es5src",
"browserify": "browserify -e ignore/es5src/app.js --outfile dist/js/app.js",
Expand Down
2 changes: 1 addition & 1 deletion src/app-model.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Rx} from '@cycle/core';
let packageJson = require('package');
let RxPackageJson = require('@cycle/core/node_modules/rx/package.json');
let RxPackageJson = require('rx/package.json');

const DEFAULT_EXAMPLE = 'merge';

Expand Down
2 changes: 1 addition & 1 deletion src/app-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function renderContent(route) {
position: 'absolute',
top: '0'},
pageRowLastChildStyle)}
,h('x-sandbox', {key: 'sandbox', route: route, width: '820px'})
,h('x-sandbox', {key: 'sandbox', route: route, width: '820px', showSubscriptions: true})
)
])
);
Expand Down
9 changes: 6 additions & 3 deletions src/components/diagram/diagram-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ function applyChangeMarbleTime(diagramData, marbleDelta) {
}

function applyChangeEndTime(diagramData, endDelta) {
var newEnd = diagramData.get('end') + endDelta;
return diagramData
.set('end', diagramData.get('end') + endDelta);
.set('end', newEnd)
.set('eventualEnd', newEnd);
}

function applyMarbleDataConstraints(marbleData) {
Expand All @@ -45,7 +47,7 @@ function applyEndTimeConstraint(diagramData) {
newEndTime = Math.round(newEndTime);
newEndTime = Math.min(newEndTime, 100);
newEndTime = Math.max(0, newEndTime);
return diagramData.set('end', newEndTime);
return diagramData.set('end', newEndTime).set('eventualEnd', newEndTime);
}

function applyDiagramDataConstraints(diagramData) {
Expand Down Expand Up @@ -76,7 +78,8 @@ function diagramModel(props, intent) {
intent.changeEndTime$,
props.get('interactive')
),
isInteractive$: props.get('interactive').startWith(false)
isInteractive$: props.get('interactive').startWith(false),
isCompact$: props.get('compact').startWith(false)
};
}

Expand Down
174 changes: 127 additions & 47 deletions src/components/diagram/diagram-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,97 +8,176 @@ import {mergeStyles, textUnselectable} from 'rxmarbles/styles/utils';

const MARBLE_WIDTH = 5; // estimate of a marble width, in percentages
const diagramSidePadding = Dimens.spaceMedium;
const diagramVerticalMargin = Dimens.spaceLarge;
const diagramArrowThickness = '2px';
const diagramArrowSidePadding = Dimens.spaceLarge;
const diagramArrowHeadSize = '8px';
const diagramArrowColor = Colors.black;
const diagramArrowColorGhost = Colors.almostWhite;
const diagramMarbleSize = Dimens.spaceLarge;
const diagramCompletionHeight = '44px';

const diagramStyle = mergeStyles({
position: 'relative',
display: 'block',
width: '100%',
height: `calc(${diagramMarbleSize} + 2 * ${diagramVerticalMargin})`,
overflow: 'visible',
cursor: 'default'},
textUnselectable
);

const diagramBodyStyle = {
position: 'absolute',
left: `calc(${diagramArrowSidePadding} + ${diagramSidePadding}
+ (${diagramMarbleSize} / 2))`,
right: `calc(${diagramArrowSidePadding} + ${diagramSidePadding}
+ (${diagramMarbleSize} / 2))`,
top: `calc(${diagramVerticalMargin} + (${diagramMarbleSize} / 2))`,
height: diagramCompletionHeight,
marginTop: `calc(0px - (${diagramCompletionHeight} / 2))`
};

function renderMarble(marbleData, isDraggable = false) {
function diagramVerticalMargin(isCompact) {
return isCompact ? Dimens.spaceSmall : Dimens.spaceLarge;
}

function diagramStyle(isCompact) {
return mergeStyles({
position: 'relative',
display: 'block',
width: '100%',
height: `calc(${diagramMarbleSize} + 2 * ${diagramVerticalMargin(isCompact)})`,
overflow: 'visible',
cursor: 'default'
},
textUnselectable
);
}

const paddingToTimeline = `(${diagramArrowSidePadding} + ${diagramSidePadding} + (${diagramMarbleSize} / 2))`;
const timelineSize = `(100% - (2 * ${paddingToTimeline}))`;
function timeLeftPosition(time) {
return `(${paddingToTimeline} + (${timelineSize} * ${time / 100}))`;
}
function timeRightPosition(time) {
return `(${paddingToTimeline} + (${timelineSize} * ${(100 - time) / 100}))`;
}

function diagramBodyStyle(isCompact) {
return {
position: 'absolute',
left: `calc(${paddingToTimeline})`,
right: `calc(${paddingToTimeline})`,
top: `calc(${diagramVerticalMargin(isCompact)} + (${diagramMarbleSize} / 2))`,
height: diagramCompletionHeight,
marginTop: `calc(0px - (${diagramCompletionHeight} / 2))`
};
}

function renderMarble(marbleData, isDraggable = false, isGhost = false) {
return h('x-marble.diagramMarble', {
key: `marble${marbleData.get('id')}`,
data: marbleData,
isDraggable,
style: {size: diagramMarbleSize}
style: {size: diagramMarbleSize},
isGhost
});
}

function renderCompletion(diagramData, isDraggable = false) {
let endTime = diagramData.get('end');
function renderEndpoints(diagramData, isDraggable = false) {
var endpoints = [
renderEndpoint(diagramData, 'start', 'diagramStart', false, false),
renderEndpoint(diagramData, 'end', 'diagramCompletion', isDraggable, false)
];

// add the eventualEndpoint if it is past the actyal end
if (diagramData.get('eventualEnd') > diagramData.get('end')) {
endpoints.push(renderEndpoint(diagramData, 'eventualEnd', 'diagramEventualEnd', false, true));
}

return endpoints;
}

function renderEndpoint(diagramData, timeName, endpointType, isDraggable, isGhost) {
let endTime = diagramData.get(timeName);
// do not render if the time is not defined, or it was at the end of our simulation
if (endTime === undefined || endTime >= 100) {
return undefined;
}

let color = isGhost ? diagramArrowColorGhost : diagramArrowColor;

let isTall = diagramData.get('notifications').some(marbleData =>
Math.abs(marbleData.get('time') - diagramData.get('end')) <= MARBLE_WIDTH*0.5
Math.abs(marbleData.get('time') - endTime) <= MARBLE_WIDTH*0.5
);
return h('x-diagram-completion.diagramCompletion', {
key: 'completion',
return h('x-diagram-completion.' + endpointType, {
key: endpointType,
time: endTime,
isDraggable,
isTall,
style: {
thickness: diagramArrowThickness,
color: diagramArrowColor,
color: color,
height: diagramCompletionHeight
}
});
}

function renderDiagramArrow() {
return h('div.diagramArrow', {style: {
backgroundColor: diagramArrowColor,
function renderDiagramArrow(data, isCompact) {
/* render the line in 3 segments:
* - to the left of 'start' render ghosted
* - render between start & end normal
* - to the right of 'end' render ghosted
*/
const arrowStyle = {
height: diagramArrowThickness,
position: 'absolute',
top: `calc(${diagramVerticalMargin} + (${diagramMarbleSize} / 2))`,
left: diagramSidePadding,
right: diagramSidePadding
}});
top: `calc(${diagramVerticalMargin(isCompact)} + (${diagramMarbleSize} / 2))`
};
let sections = [];
let start = data.get('start');
let end = data.get('end');
let middleStart = diagramSidePadding;
let middleEnd = diagramSidePadding;

sections.push(h('div.diagramArrow', {
style: mergeStyles(arrowStyle, {
backgroundColor: diagramArrowColorGhost,
left: middleStart,
right: `calc(${timeRightPosition(start)})`
})
}));
middleStart = `calc(${timeLeftPosition(start)})`;

if (end < 100) {
sections.push(h('div.diagramArrow', {
style: mergeStyles(arrowStyle, {
backgroundColor: diagramArrowColorGhost,
left: `calc(${timeLeftPosition(end)})`,
right: middleEnd
})
}));
middleEnd = `calc(${timeRightPosition(end)})`;
}

if (start < end) {
sections.push(h('div.diagramArrow', {
style: mergeStyles(arrowStyle, {
backgroundColor: diagramArrowColor,
left: middleStart,
right: middleEnd
})
}));
}

return sections;
}

function renderDiagramArrowHead() {
function renderDiagramArrowHead(data, isCompact) {
let end = data.get('end');
let isGhost = end < 100;
let color = isGhost ? diagramArrowColorGhost : diagramArrowColor;
return h('div.diagramArrowHead', {style: {
width: 0,
height: 0,
borderTop: `${diagramArrowHeadSize} solid transparent`,
borderBottom: `${diagramArrowHeadSize} solid transparent`,
borderLeft: `calc(2 * ${diagramArrowHeadSize}) solid ${diagramArrowColor}`,
borderLeft: `calc(2 * ${diagramArrowHeadSize}) solid ${color}`,
display: 'inline-block',
right: `calc(${diagramSidePadding} - 1px)`,
position: 'absolute',
top: `calc(${diagramVerticalMargin} + (${diagramMarbleSize} / 2)
top: `calc(${diagramVerticalMargin(isCompact)} + (${diagramMarbleSize} / 2)
- ${diagramArrowHeadSize} + (${diagramArrowThickness} / 2))`
}});
}

function renderDiagram(data, isInteractive) {
function renderDiagram(data, isInteractive, isCompact) {
let marblesVTree = data.get('notifications')
.map(notification => renderMarble(notification, isInteractive))
.map(notification => renderMarble(notification, isInteractive, notification.get('time') > (data.get('end') + 0.01)))
.toArray(); // from Immutable.List
let completionVTree = renderCompletion(data, isInteractive);
return h('div', {style: diagramStyle}, [
renderDiagramArrow(),
renderDiagramArrowHead(),
h('div', {style: diagramBodyStyle}, [completionVTree].concat(marblesVTree))
return h('div', {style: diagramStyle(isCompact)}, [
renderDiagramArrow(data, isCompact),
renderDiagramArrowHead(data, isCompact),
h('div', {style: diagramBodyStyle(isCompact)}, renderEndpoints(data, isInteractive).concat(marblesVTree))
])
}

Expand Down Expand Up @@ -147,6 +226,7 @@ function diagramView(model) {
vtree$: Rx.Observable.combineLatest(
animateData$(model.data$).merge(model.newData$),
model.isInteractive$,
model.isCompact$,
renderDiagram
)
};
Expand Down
Loading