56 Commits

Author SHA1 Message Date
Bogdan Lyashenko
4112828108 1.6.2 2019-07-09 20:36:03 +02:00
Bogdan Lyashenko
17e5edc17d fix: ide integration 2019-07-09 20:35:54 +02:00
Bogdan Lyashenko
24a0f6f6c4 fix: readme fixes 2019-07-09 19:42:51 +02:00
Bogdan Lyashenko
76975298f0 1.6.1 2019-07-08 20:53:32 +02:00
Bogdan Lyashenko
770ae6d5cf fix: add test vue file 2019-07-08 20:53:13 +02:00
Bohdan Liashenko
25fdb28540 Merge pull request #68 from blackfyre/patch-1
Updated JS file list
2019-07-08 20:50:02 +02:00
Meki
6a026e0039 Updated JS file list
As per Bogdan's suggestion, the JS list has been expanded to support Vue single file components as well. https://github.com/Bogdan-Lyashenko/codecrumbs/issues/26#issuecomment-509145766
2019-07-08 11:28:50 +02:00
Bogdan Lyashenko
edb8cd0ba7 1.6.0 2019-07-07 14:05:25 +02:00
Bogdan Lyashenko
0908fcab89 feat: move to less 2019-07-07 14:05:04 +02:00
Bogdan Lyashenko
ceb18f613f 1.5.7 2019-07-02 20:42:20 +02:00
Bogdan Lyashenko
72776eee35 fix: build script 2019-07-02 20:41:58 +02:00
Bogdan Lyashenko
0cf67aa8bb fix: babel load 2019-06-30 21:09:45 +02:00
Bogdan Lyashenko
1893aef144 fix: server config 2019-06-30 15:47:43 +02:00
Bogdan Lyashenko
d2806e7fe0 fix: standalone flag 2019-06-30 14:05:35 +02:00
Bogdan Lyashenko
174e4be581 fix: meta version update 2019-06-30 13:57:31 +02:00
Bogdan Lyashenko
583b47bf2f 1.5.3 2019-06-30 13:55:01 +02:00
Bogdan Lyashenko
b623363369 fix: clen up 2019-06-30 13:54:56 +02:00
Bogdan Lyashenko
2b72adbfed 1.5.2 2019-06-23 19:02:24 +02:00
Bogdan Lyashenko
2b1f1a514d fix: version assigning logic 2019-06-23 19:01:46 +02:00
Bogdan Lyashenko
af452c014d 1.5.1 2019-06-23 18:42:19 +02:00
Bogdan Lyashenko
53cfa8deee fix: remove shared code 2019-06-23 18:42:05 +02:00
Bogdan Lyashenko
adefb7de07 1.5.0 2019-06-23 14:16:18 +02:00
Bogdan Lyashenko
d17ba78413 fix: relative path 2019-06-23 14:16:08 +02:00
Bogdan Lyashenko
56419385c3 1.4.7 2019-06-23 11:55:45 +02:00
Bogdan Lyashenko
4b55018014 fix: build for standalone 2019-06-23 11:54:44 +02:00
Bogdan Lyashenko
449b4157c3 1.4.6 2019-06-22 20:15:15 +02:00
Bogdan Lyashenko
cad0113d59 feat: add integration for io 2019-06-22 20:15:07 +02:00
Bogdan Lyashenko
4e98fd7839 1.4.5 2019-05-30 11:57:01 +02:00
Bogdan Lyashenko
366eb9d0dd fix: details for single crumbs 2019-05-30 11:56:51 +02:00
Bogdan Lyashenko
ed6cb9e00d 1.4.4 2019-05-23 20:17:54 +02:00
Bogdan Lyashenko
9267c05a9b fix: layout spacing 2019-05-23 20:17:44 +02:00
Bogdan Lyashenko
e2d574eb5d 1.4.3 2019-05-23 19:23:17 +02:00
Bohdan Liashenko
658fe92f9e Merge pull request #57 from jbcam/fix-cli-flag-ts
fix: ts cli settings
2019-05-23 19:22:05 +02:00
Jean Baptiste Camaret
1525572c03 fix cli settings 2019-05-21 11:36:42 +02:00
Bogdan Lyashenko
90b548973b 1.4.2 2019-05-20 19:29:03 +02:00
Bogdan Lyashenko
fa188868b1 fix: layout calc 2019-05-20 19:28:51 +02:00
Bogdan Lyashenko
719ee3456a 1.4.1 2019-05-20 19:18:20 +02:00
Bogdan Lyashenko
afc136d4f9 fix: geometry calc for layout 2019-05-20 19:17:33 +02:00
Bogdan Lyashenko
802ceb1ff5 fix: clean up 2019-05-20 19:08:12 +02:00
Bohdan Liashenko
adf9aac96a Merge pull request #53 from jbcam/add-tsConfig-suport-madge
feat: add support for madge to resolve tsConfig path aliases
2019-05-20 18:59:36 +02:00
Jean Baptiste Camaret
1898ff0813 updates post review 2019-05-17 11:33:44 +02:00
Bogdan Lyashenko
e97ada9654 1.4.0 2019-05-14 20:52:27 +02:00
Bogdan Lyashenko
1f79a454c4 fix: tree diagram width 2019-05-14 20:52:16 +02:00
Bogdan Lyashenko
029493f3ed feat: add code cmp 2019-05-14 20:38:31 +02:00
Bogdan Lyashenko
882332fc55 Merge branch 'master' into code-preview 2019-05-14 19:46:46 +02:00
Bogdan Lyashenko
a318765143 1.3.1 2019-05-14 19:38:33 +02:00
Bogdan Lyashenko
bafed33c1f fix: add default value for ccAlign point 2019-05-14 19:37:30 +02:00
Bogdan Lyashenko
43451bdaff fix: cc comments 2019-05-14 19:36:20 +02:00
Bogdan Lyashenko
a2c9b59a1e feat: code preview 2019-05-14 19:19:08 +02:00
Bogdan Lyashenko
164cb11cf3 fix: version 2019-05-12 18:01:33 +02:00
Bogdan Lyashenko
84fab1da37 fix: max width for ns 2019-05-12 15:05:35 +02:00
Bogdan Lyashenko
9843fb0144 fix: external edge 2019-05-12 13:24:18 +02:00
Bogdan Lyashenko
8b23750641 fix: colors for cc 2019-05-12 12:13:01 +02:00
Bogdan Lyashenko
3d775da19f fix: move steps calc to top 2019-05-05 20:33:29 +02:00
Bogdan Lyashenko
ec0880ade3 feat: new sorting for cc 2019-05-04 20:14:49 +02:00
Jean Baptiste Camaret
e3cfb240d0 feat: add support for tsConfig path aliases 2019-04-18 16:39:41 +02:00
134 changed files with 1016 additions and 4504 deletions

2
.gitignore vendored
View File

@@ -3,7 +3,7 @@ node_modules
# Build directories
src/public/dist/local/bundle/
src/public/dist/standalone/bundle/
src/public/dist/standalone-build/
# example for dev
# example-project

View File

@@ -1,3 +1,4 @@
.idea
example-project
docs
docs
src/public/js

View File

@@ -23,12 +23,14 @@
>
>**How it works?** You run `codecrumbs` command for a codebase, it analyzes source code and builds its visual representation. Write down a codecrumb-comment and codebase state will be reflected by visual client in browser on the fly.
>
> Check out [my talk at React-Finland](https://www.youtube.com/watch?v=S_1-1jzLxm4) for more details.
>
>-[@bliashenko](https://twitter.com/bliashenko)
## Demo
Check out the example of [**standalone version running here**](https://codecrumbs.io/#showcase=todo-react-redux).
<img src="/docs/main-ui-2.png" width="100%"/>
<img src="/docs/main-ui-3.png" width="100%"/>
## Get started
### Install and run
@@ -44,19 +46,20 @@ Parameter | Description | Example
```-d```, ```--dir``` | Relative path to project source code directory | ```-d src```
```-e```, ```--entry``` | Relative path to project source entry point file (must be inside ```dir```) | ```-e src/app.js```
```-x```, ```--excludeDir``` | Relative path(or paths separated by ```,```) to directories for exclusion | ```-x src/doc,src/thirdparty```
```-i```, ```--ideCmd``` | command to open file in IDE from bash (default 'webstorm') | ```-i code```
```-p```, ```--port``` | Port for Codecrumbs client (optional, default *2018*) | ```-p 2019```
```-n```, ```--projectName``` | Project name alias (optional, default same as ```-d``` value) | ```-n my-hello-world```
## Features
### Breadcrumbs and trails
<img src="/docs/cc-ui-2.png" width="750"/>
<img src="/docs/cc-ui-3.png" width="750"/>
UI explained:
- enable "Codecrumbs" switch to have codecrumbs tree on the scheme (drop-down contains extra configuration)
- choose "current" codecrumbs trail to display (can be either trail or all other "simple" codecrumbs)
- select connection between two steps (code for two codecrumbs will be opened in "Sidebar" under "Crumbs" tab)
- set other options in dropdowns to configure behaviour of the diagram
- set other options in dropdowns to configure behaviour of the diagram (show code blocks, details, etc.)
**How to get there?**
@@ -80,7 +83,7 @@ Simply start codecrumbs multiple times (once for each codebase), it all **will b
E.g. for client-server application, go to the source directory for your server code and run `codecrumbs -e your-server-src/index.py -d your-server-src`, same for client `codecrumbs -e src-client/index.js -d src-client`.
> **Note:** codebases can be located wherever you want (**no** need to have them like mono-repo, etc.), simply run `codecrumbs` for directory you need.
<img src="/docs/multi-codebase-cc.png" width="100%"/>
<img src="/docs/multi-codebase-cc-2.png" width="100%"/>
### Multi-language support
Current version supports next programming languages:
@@ -121,6 +124,13 @@ UI explained:
[js2flowchart](https://github.com/Bogdan-Lyashenko/js-code-to-svg-flowchart) is used in the sidebar to draw flowchart for the selected file code.
### IDE integration
> Check ```-i``` CLI param first to configure command.
Navigate from browser to your code editor simply by clicking ```Command+click```(or ```Alt+click```) on a file or a codecrumb to open file in your IDE.
<img src="/docs/ide-integration.gif" width="100%"/>
## Case studies
The tool (codecrumbs) allows us to learn, document and explain a codebase much faster. Also, with *Download & Upload* feature it becomes super easy to collect and share your "investigation results".

17
cli/index.cli.js Normal file → Executable file
View File

@@ -7,16 +7,17 @@ const server = require('../src/server');
program
.option('-e, --entry [entryFile]', 'Specify path to entry point file. E.g. `src/app.js`')
.option(
'-d, --dir [projectDir]',
'Specify path to project source code directory. E.g. `src`',
''
)
.option('-d, --dir [projectDir]', 'Specify path to project source code directory. E.g. `src`', '')
.option(
'-w, --webpack [webpackConfigFile]',
'Specify path to webpack config file. E.g. webpack.config.js'
)
.option(
'-t, --tsconfig [tsConfigFile]',
'Specify path to typeScript config file. E.g. tsConfig.json'
)
.option('-p, --port [defaultPort]', 'Specify port for Codecrumbs client. E.g. 3333', 2018)
.option('-i, --ideCmd [ideCmd]', 'IDE command to open file')
.option('-x, --excludeDir [excludeDirectories]', 'Exclude directories')
.option('-n, --projectName [projectNameAlias]', 'Project name alias')
.parse(process.argv);
@@ -36,8 +37,10 @@ server.setup(
entryPoint: program.entry,
projectDir: program.dir,
webpackConfigPath: program.webpack,
tsConfigPath: program.tsconfig,
clientPort: program.port,
excludeDir: program.excludeDir
excludeDir: program.excludeDir,
ideCmd: program.ideCmd
},
false
{ isDev: false }
);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

BIN
docs/cc-ui-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
docs/ide-intergation.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

BIN
docs/main-ui-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -1,7 +1,7 @@
#include <iostream>
using namespace std;
// cc:main function
//cc:main function
int main()
{
cout << "Hello, World!";

View File

@@ -1,4 +1,4 @@
// cc:main function
//cc:main function
using System;
namespace HelloWorld
{

View File

@@ -1,6 +1,6 @@
public class HelloWorld {
// cc: main function
//cc: main function
public static void main(String[] args) {
// Prints "Hello, World" to the terminal window.
System.out.println("Hello, World");

View File

@@ -1,4 +1,4 @@
// cc:main function
//cc:main function
function greeting() {
console.log('Hello world!');
}

View File

@@ -1,4 +1,4 @@
// cc:main function
//cc:main function
fun main(args : Array<String>) {
println("Hello, World!")

View File

@@ -1,5 +1,5 @@
<?php
// cc:main function
//cc:main function
echo "Hello World!";
echo "PHP is so easy!";
?>

View File

@@ -1,4 +1,4 @@
// cc:main function
//cc:main function
function greeting() {
console.log('Hello world!');
}

View File

@@ -10,7 +10,7 @@ import {
function authenticate(provider) {
return dispatch => {
//cc:signin#1;firebase sign in;+2;call to firebase with auth provider, proceed if success response
//cc:signin#1;firebase sign in;+1;call to firebase with auth provider, proceed if success response
firebaseAuth.signInWithPopup(provider)
.then(result => dispatch(signInSuccess(result)))
.catch(error => dispatch(signInError(error)));

View File

@@ -13,7 +13,7 @@ export function authReducer(state = new AuthState(), {payload, type}) {
case INIT_AUTH:
case SIGN_IN_SUCCESS:
return state.merge({
authenticated: !!payload, // cc:signin#5;toggle 'authenticated' flag
authenticated: !!payload, //cc:signin#5;toggle 'authenticated' flag
id: payload ? payload.uid : null
});

View File

@@ -1,4 +1,4 @@
//cc:firebase config
//cc:firebase config;and some details
export const firebaseConfig = {
apiKey: 'AIzaSyBsVVpEDrlNPEmshLcmOuE0FxhjPn0AqMg',
authDomain: 'todo-react-redux.firebaseapp.com',

View File

@@ -1,4 +1,4 @@
import createHistory from 'history/createBrowserHistory';
export default createHistory();
export default createHistory();

View File

@@ -0,0 +1,22 @@
<template>
<p>{{ greeting }} World!</p>
</template>
<script>
module.exports = {
data: function () {
return {
greeting: 'Hello'
}
}
}
</script>
//cc:test vue
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>

View File

@@ -10,7 +10,7 @@ import RequireUnauthRoute from '../components/require-unauth-route';
import SignInPage from '../pages/sign-in';
import TasksPage from '../pages/tasks';
//cc:layout#1;describe pages
//cc:layout#1;describe pages;some details long description for separare popup
const App = ({authenticated, signOut}) => (
<div>
<Header

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom'
//cc:signin#6;enable route;+6
//cc:signin#6;enable route;details
const RequireAuthRoute = ({component: Component, authenticated, ...rest}) => (
<Route
{...rest}

View File

@@ -6,7 +6,7 @@ import Icon from '../icon';
import './task-item.css';
//cc:there is task
//cc:there is task;extra
export class TaskItem extends Component {
constructor() {
super(...arguments);

View File

@@ -37,7 +37,7 @@ const mapDispatchToProps = {
signInWithGoogle: authActions.signInWithGoogle,
signInWithTwitter: authActions.signInWithTwitter
};
//cc:signin#7;test
export default withRouter(
connect(
null,

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { Card, CardHeader, CardContent } from '@material-ui/core';
import { LoginForm } from './loginForm';
import { LoginForm } from '@src/components/login/loginForm';
import { isValidLogin } from '../../api/login';
import { LoginEntity, createEmptyLogin } from '../../model';
import { NotificationComponent } from '../../common/components/notification';

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "example-project",
"moduleResolution": "node",
"paths": {
"@src/*": ["src-typescript/*"]
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "codecrumbs",
"version": "1.2.14",
"version": "1.6.2",
"author": "Bohdan Liashenko",
"license": "BSD-3-Clause",
"repository": {
@@ -14,8 +14,10 @@
"client-dev": "cd src/public && webpack --config webpack.dev.js --progress --colors --watch --env dev",
"server-dev": "nodemon src/index.dev.js",
"server-debug": "nodemon --inspect src/index.dev.js",
"build": "cd src/public && webpack --config webpack.prod.js --progress --colors",
"start:standalone": "cd src/public/dist/standalone && http-server",
"clean": "rm -rf src/public/dist/standalone-build",
"babel-compile-standalone": "babel src/public/js -d src/public/dist/standalone-build --config-file ./src/public/babel.config.js --copy-files",
"webpack-compile-local": "cd src/public && webpack --config webpack.local.js --progress",
"build": "yarn clean && yarn babel-compile-standalone && yarn webpack-compile-local",
"pretty": "prettier --write \"./src/public/js/**/*.js\""
},
"bin": {
@@ -23,7 +25,6 @@
},
"dependencies": {
"@babel/parser": "^7.1.2",
"@babel/polyfill": "^7.0.0",
"@babel/traverse": "^7.1.0",
"antd": "^3.9.2",
"chalk": "^2.4.2",
@@ -42,7 +43,6 @@
"portscanner": "^2.2.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-draggable": "^3.0.5",
"react-redux": "^5.0.7",
"react-syntax-highlighter": "8.0.1",
"redux": "^4.0.0",
@@ -54,20 +54,23 @@
"websocket": "1.0.27"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.1.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.0.0",
"@commitlint/cli": "^7.3.2",
"@commitlint/config-conventional": "^7.3.1",
"babel-loader": "^8.0.4",
"babel-plugin-import": "^1.9.1",
"babel-plugin-transform-define": "^1.3.1",
"css-loader": "^0.28.11",
"husky": "^1.3.1",
"node-sass": "^4.9.3",
"less": "^3.9.0",
"less-loader": "^5.0.0",
"nodemon": "^1.18.7",
"prettier": "^1.14.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.21.0",
"webpack": "^4.20.2",
"webpack-bundle-analyzer": "^3.0.3",

View File

@@ -16,11 +16,12 @@ const namespaceTwo = {
};
const namespaceTypeScriptExample = {
projectNameAlias: 'ts-example-server',
projectDir: `example-project/src-typescript`,
entryPoint: `example-project/src-typescript/index.tsx`,
clientPort: 2018
};
projectNameAlias: 'ts-example-server',
projectDir: `example-project/src-typescript`,
entryPoint: `example-project/src-typescript/index.tsx`,
tsConfigPath: `example-project/src-typescript/tsConfig.json`,
clientPort: 2018
};
const namespaceDebug = {
projectNameAlias: 'debug',
@@ -38,9 +39,8 @@ const namespaceLanguageTest = {
const args = process.argv.slice(2);
const namespaces = {
two: namespaceTwo,
ts: namespaceTypeScriptExample
two: namespaceTwo,
ts: namespaceTypeScriptExample
};
const namespace = namespaces[args[0]] !== undefined ? namespaces[args[0]] : namespaceOne;
const isDev = true;
server.setup(namespace, isDev);
server.setup(namespace, { isDev: true });

View File

@@ -0,0 +1,35 @@
const packageJson = require('../../package');
module.exports = function(app) {
app.cache(true);
const presets = [
[
'@babel/preset-env',
{
targets: {
browsers: ['last 2 versions']
},
modules: false
}
],
'@babel/preset-react'
];
const plugins = [
['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }],
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-transform-runtime',
[
'transform-define',
{
'process.env.CODECRUMBS_VERSION': packageJson.version
}
]
];
return {
presets,
plugins
};
};

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Codecrumbs standalone: learn and share your code knowledge!</title>
<style>
@font-face {
font-family: menlo-regular;
src: url('Menlo-Regular.ttf');
}
svg { font-family: menlo-regular, monospace; }
</style>
</head>
<body>
<div id="mount-node" style="height: 100%">
<div id="placeholder" style="text-align: center; color: #1890ff">
Loading standalone codecrumbs experience...
</div>
</div>
<script src="./bundle/main.bundle.js" type="text/javascript"></script>
<script type="text/javascript">
(function(window) {
if (!window.codecrumbs) {
console.error('Codecrumbs project is not loaded!');
return false;
}
var hash = location.hash;
var key = '#showcase=';
var showCaseName = hash.slice(hash.indexOf(key) + key.length) || 'todo-react-redux';
var fileElement = document.createElement('div');
fileElement.innerText = 'Fetching "' + showCaseName + '" showcase...';
document.getElementById('placeholder').appendChild(fileElement);
window.fetch('./json/' + showCaseName + '.json')
.then(function(response) {
return response.json();
}).then((object) => {
window.codecrumbs.default({ standalone: true, predefinedState: object.data }, 'mount-node');
}).catch((e) => {
console.error(e);
document.getElementById('placeholder').innerText = 'Ooopps.. :( Failed to load. ' +
'Set hash params and reload page. E.g. #showcase=todo-react-redux'
});
})(window)
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,32 @@
import React, { Suspense } from 'react';
import Spin from 'antd/lib/spin';
import 'antd/lib/spin/style/css';
import { isMobile } from 'utils/index';
import Spin from 'antd/es/spin';
import 'antd/es/spin/style';
const DataBus = React.lazy(() => import(/* webpackChunkName: "data-bus" */ 'core/dataBus'));
import { isMobile } from './utils/index';
const DataBus = React.lazy(() => import(/* webpackChunkName: "data-bus" */ './core/dataBus'));
const ViewsSwitches = React.lazy(() =>
import(/* webpackChunkName: "view-switches" */ 'components/topBar/controls/ViewSwitches/ViewSwitchesContainer')
import(/* webpackChunkName: "view-switches" */ './components/topBar/controls/ViewSwitches/ViewSwitchesContainer')
);
const TopBar = React.lazy(() =>
import(/* webpackChunkName: "top-bar" */ 'components/topBar/subPanel/SubPanelContainer')
import(/* webpackChunkName: "top-bar" */ './components/topBar/subPanel/SubPanelContainer')
);
const TreeDiagramsContainer = React.lazy(() =>
import(/* webpackChunkName: "tree-diagram" */ 'components/treeDiagram/TreeDiagramsContainer')
import(/* webpackChunkName: "tree-diagram" */ './components/treeDiagram/TreeDiagramsContainer')
);
const SideBar = React.lazy(() =>
import(/* webpackChunkName: "side-bar" */ 'components/sideBar/SideBarContainer')
import(/* webpackChunkName: "side-bar" */ './components/sideBar/SideBarContainer')
);
const ExplorerBar = React.lazy(() =>
import(/* webpackChunkName: "explorer-bar" */ 'components/explorerBar/ExplorerBarContainer')
import(/* webpackChunkName: "explorer-bar" */ './components/explorerBar/ExplorerBarContainer')
);
import './App.scss';
const Footer = React.lazy(() =>
import(/* webpackChunkName: "explorer-bar" */ './components/footer')
);
import './App.less';
const App = (props = {}) => {
return (
@@ -59,14 +64,9 @@ const App = (props = {}) => {
</div>
<footer className="footer">
<span>{`v${process.env.VERSION}`}</span>
<span>
&#9400; Bohdan Liashenko
{' • '}
<a target="_blank" href="https://github.com/Bogdan-Lyashenko/codecrumbs">Github</a>
{' • '}
<a target="_blank" href="https://codecrumbs.io/">codecrumbs.io</a>
</span>
<Suspense fallback={null}>
<Footer />
</Suspense>
</footer>
</div>
);

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { connect } from 'react-redux';
import { getSource, getSourceLayout } from 'core/dataBus/selectors';
import { getCheckedState } from 'core/controlsBus/selectors';
import { getActiveNamespace } from 'core/namespaceIntegration/selectors';
import { getSource, getSourceLayout } from '../../core/dataBus/selectors';
import { getCheckedState } from '../../core/controlsBus/selectors';
import { getActiveNamespace } from '../../core/namespaceIntegration/selectors';
import ExplorerBar from './component/ExplorerBar';

View File

@@ -1,8 +1,10 @@
import React from 'react';
import { Tree } from 'antd';
import { FILE_NODE_TYPE } from 'core/constants';
import './ExplorerBar.scss';
import Tree from 'antd/es/tree'
import 'antd/es/tree/style'
import { FILE_NODE_TYPE } from '../../../core/constants';
import './ExplorerBar.less';
const DirectoryTree = Tree.DirectoryTree;
const TreeNode = Tree.TreeNode;

View File

@@ -0,0 +1,20 @@
import React from 'react';
import metaInfo from '../../meta';
export default () => (
<React.Fragment>
<span>{`v${metaInfo.version}`}</span>
<span>
&#9400; Bohdan Liashenko
{' • '}
<a target="_blank" href="https://github.com/Bogdan-Lyashenko/codecrumbs">
Github
</a>
{' • '}
<a target="_blank" href="https://codecrumbs.io/">
codecrumbs.io
</a>
</span>
</React.Fragment>
);

View File

@@ -1,10 +1,10 @@
import React from 'react';
import { connect } from 'react-redux';
import { getActiveNamespace } from 'core/namespaceIntegration/selectors';
import { getSourceUserChoice, getSource, getProjectMetadata } from 'core/dataBus/selectors';
import { toggleSwitch, selectSideBarTab } from 'core/controlsBus/actions';
import { getCheckedState, getValuesState } from 'core/controlsBus/selectors';
import { getActiveNamespace } from '../../core/namespaceIntegration/selectors';
import { getSourceUserChoice, getSource, getProjectMetadata } from '../../core/dataBus/selectors';
import { toggleSwitch, selectSideBarTab } from '../../core/controlsBus/actions';
import { getCheckedState, getValuesState } from '../../core/controlsBus/selectors';
import SideBar from './component/SideBar';
const SideBarContainer = ({ sideBar, ...otherProps }) => {

View File

@@ -3,9 +3,9 @@ import classNames from 'classnames';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { atomOneLight } from 'react-syntax-highlighter/styles/hljs';
import './index.scss';
import './index.less';
const FONT_SIZE = '12px';
const FONT_SIZE = 12;
const LINE_HEIGHT = 18;
const PADDING_TOP = 5;
//TODO: add select with several themes
@@ -13,7 +13,7 @@ const PADDING_TOP = 5;
//https://github.com/conorhastings/react-syntax-highlighter/blob/master/README.md
export default class extends React.Component {
fixScroll() {
const { dependenciesLines = [], crumbedLines = [] } = this.props;
const { dependenciesLines = [], crumbedLines = [], lineHeight } = this.props;
if (!this.codeRef || !this.codeRef.scrollTo) {
return;
}
@@ -24,7 +24,8 @@ export default class extends React.Component {
? crumbedLines
: null;
lines && this.codeRef.scrollTo(0, (lines[0][0] - 1) * LINE_HEIGHT + PADDING_TOP - 2);
lines &&
this.codeRef.scrollTo(0, (lines[0][0] - 1) * (lineHeight || LINE_HEIGHT) + PADDING_TOP - 2);
}
componentDidUpdate(prevProps) {
this.fixScroll();
@@ -34,7 +35,14 @@ export default class extends React.Component {
}
render() {
const { language, code, crumbedLines = [], dependenciesLines = [], limitedHeight } = this.props;
const {
language,
code,
crumbedLines = [],
dependenciesLines = [],
limitedHeight,
fontSize
} = this.props;
// TODO: calc height for .Code based on dependenciesLines - it's not always need to be 300 px!!
return (
@@ -44,7 +52,10 @@ export default class extends React.Component {
style={atomOneLight}
showLineNumbers={true}
wrapLines={true}
customStyle={{ fontSize: FONT_SIZE, padding: `${PADDING_TOP}px 0px 5px 5px` }}
customStyle={{
fontSize: `${fontSize || FONT_SIZE}px`,
padding: `${PADDING_TOP}px 0px 5px 5px`
}}
lineProps={lineNumber => {
if (isMatchLineNumber(crumbedLines, lineNumber)) {
return { className: 'crumbedLine' };

View File

@@ -1,14 +1,18 @@
import React from 'react';
import { connect } from 'react-redux';
import { Collapse, Alert } from 'antd';
import { NO_TRAIL_FLOW } from 'shared-with-server-src/constants';
import { getCodeCrumbsUserChoice } from 'core/dataBus/selectors';
import { getNamespacesList } from 'core/dataBus/selectors';
import { gatherFlowStepsData } from 'components/treeDiagram/component/Tree/CodeCrumbs/helpers';
import Collapse from 'antd/es/collapse'
import 'antd/es/collapse/style'
import Alert from 'antd/es/alert'
import 'antd/es/alert/style'
import { NO_TRAIL_FLOW } from '../../../../shared-constants';
import { getCodeCrumbsUserChoice } from '../../../../core/dataBus/selectors';
import { getNamespacesList } from '../../../../core/dataBus/selectors';
import { gatherFlowStepsData } from '../../../treeDiagram/component/Tree/CodeCrumbs/helpers';
import Code from '../Code';
import './index.scss';
import './index.less';
const Panel = Collapse.Panel;
@@ -65,10 +69,9 @@ const mapStateToProps = (state, props) => {
namespace
});
const { ccFilesLayoutMapNs, sortedFlowSteps } = gatherFlowStepsData({
const { involvedNsData, sortedFlowSteps } = gatherFlowStepsData(state, {
currentSelectedCrumbedFlowKey,
namespacesList,
state
namespacesList
});
if (currentSelectedCrumbedFlowKey === NO_TRAIL_FLOW) {
@@ -76,7 +79,7 @@ const mapStateToProps = (state, props) => {
flowStepsFiles: getUnTrailedCodecrumbs(
currentSelectedCrumbedFlowKey,
codeCrumbedFlowsMap,
ccFilesLayoutMapNs[namespace]
involvedNsData[namespace].codecrumbsLayoutMap
)
};
}
@@ -87,7 +90,7 @@ const mapStateToProps = (state, props) => {
: sortedFlowSteps
).map(item => ({
...item,
file: ccFilesLayoutMapNs[item.namespace][item.filePath].data
file: involvedNsData[item.namespace].codecrumbsLayoutMap[item.filePath].data
}))
};
};

View File

@@ -1,8 +1,12 @@
import React from 'react';
import { connect } from 'react-redux';
import { Collapse, Alert } from 'antd';
import { getSource, getSourceUserChoice, getDependenciesUserChoice } from 'core/dataBus/selectors';
import Collapse from 'antd/es/collapse'
import 'antd/es/collapse/style'
import Alert from 'antd/es/alert'
import 'antd/es/alert/style'
import { getSource, getSourceUserChoice, getDependenciesUserChoice } from '../../../../core/dataBus/selectors';
import Code from '../Code';
import {
@@ -10,7 +14,7 @@ import {
findFileNode,
extractExportsForImports
} from '../shared/utils';
import './index.scss';
import './index.less';
const Panel = Collapse.Panel;

View File

@@ -1,8 +1,11 @@
import React from 'react';
import { Spin, Alert } from 'antd';
import Alert from 'antd/es/alert'
import 'antd/es/alert/style'
import Spin from 'antd/es/spin'
import 'antd/es/spin/style'
import './index.scss';
import './index.less';
const Styles = {
strokeColor: '#00bcd4',

View File

@@ -1,8 +1,13 @@
import React, { Suspense } from 'react';
import { Tabs } from 'antd';
import { Skeleton, Alert } from 'antd';
import { Copy } from 'components/topBar/controls/Copy';
import Tabs from 'antd/es/tabs'
import 'antd/es/tabs/style'
import Skeleton from 'antd/es/skeleton'
import 'antd/es/skeleton/style'
import Alert from 'antd/es/alert'
import 'antd/es/alert/style'
import { Copy } from '../../topBar/controls/Copy';
const Code = React.lazy(() => import(/* webpackChunkName: "code" */ './Code'));
const DependenciesTab = React.lazy(() =>
@@ -13,7 +18,7 @@ const FlowChartTab = React.lazy(() =>
import(/* webpackChunkName: "flow-chart-tab" */ './FlowChartTab')
);
import './SideBar.scss';
import './SideBar.less';
const TabPane = Tabs.TabPane;
@@ -31,7 +36,7 @@ export default ({
onTabSelect
}) => {
const file = selectedNode && filesMap[selectedNode.path];
const standaloneNoCode = process.env.STANDALONE && (!file || !file.fileCode);
const standaloneNoCode = !process.env.LOCAL && (!file || !file.fileCode);
const header = standaloneNoCode ? (
<Alert
message="No code for this file in standalone mode."

View File

@@ -1,5 +1,8 @@
import { Icon } from 'antd';
import React from 'react';
import Icon from 'antd/es/icon'
import 'antd/es/icon/style'
import copy from 'copy-text-to-clipboard';
export const Copy = ({ copyText }) => (

View File

@@ -1,12 +1,18 @@
import React from 'react';
import { connect } from 'react-redux';
import { Menu, Dropdown, Button } from 'antd';
import { NO_TRAIL_FLOW } from 'core/constants';
import { selectCodeCrumbedFlow } from 'core/dataBus/actions';
import { getCodeCrumbsUserChoice } from 'core/dataBus/selectors';
import { getCheckedState } from 'core/controlsBus/selectors';
import './index.scss';
import Menu from 'antd/es/menu'
import 'antd/es/menu/style'
import Dropdown from 'antd/es/dropdown'
import 'antd/es/dropdown/style'
import Button from 'antd/es/button'
import 'antd/es/button/style'
import { NO_TRAIL_FLOW } from '../../../../core/constants';
import { selectCodeCrumbedFlow } from '../../../../core/dataBus/actions';
import { getCodeCrumbsUserChoice } from '../../../../core/dataBus/selectors';
import { getCheckedState } from '../../../../core/controlsBus/selectors';
import './index.less';
const FlowSelect = ({
codeCrumbsDiagramOn,

View File

@@ -1,9 +1,19 @@
import React from 'react';
import { connect } from 'react-redux';
import { Menu, Dropdown, Button, Icon, Upload } from 'antd';
import { downloadStore, uploadStore } from 'core/dataBus/actions';
import './index.scss';
import Menu from 'antd/es/menu'
import 'antd/es/menu/style'
import Dropdown from 'antd/es/dropdown'
import 'antd/es/dropdown/style'
import Icon from 'antd/es/icon'
import 'antd/es/icon/style'
import Button from 'antd/es/button'
import 'antd/es/button/style'
import Upload from 'antd/es/upload'
import 'antd/es/upload/style'
import { downloadStore, uploadStore } from '../../../../core/dataBus/actions';
import './index.less';
const SettingsControl = ({ onDownload, onUpload }) => {
const uploadProps = {

View File

@@ -1,8 +1,16 @@
import React from 'react';
import { Switch, Menu, Dropdown, Icon } from 'antd';
import { VIEW_TYPES } from 'core/controlsBus/constants';
import './ViewSwitch.scss';
import Switch from 'antd/es/switch'
import 'antd/es/switch/style'
import Menu from 'antd/es/menu'
import 'antd/es/menu/style'
import Dropdown from 'antd/es/dropdown'
import 'antd/es/dropdown/style'
import Icon from 'antd/es/icon'
import 'antd/es/icon/style'
import { VIEW_TYPES } from '../../../../../core/controlsBus/constants';
import './ViewSwitch.less';
class ViewSwitch extends React.Component {
renderMenu() {

View File

@@ -1,12 +1,11 @@
import React from 'react';
import classNames from 'classnames';
import FlowSelect from 'components/topBar/controls/FlowSelect/index';
import ZoomControl from 'components/topBar/controls/ZoomControl/index';
import SettingsControl from 'components/topBar/controls/SettingsControl/index';
import FlowSelect from '../../FlowSelect/index';
import SettingsControl from '../../SettingsControl/index';
import ViewSwitch from '../Item/ViewSwitch';
import './ViewSwitchList.scss';
import './ViewSwitchList.less';
const ViewSwitchList = props => {
const {

View File

@@ -1,12 +1,12 @@
import React from 'react';
import { connect } from 'react-redux';
import { getActiveNamespace } from 'core/namespaceIntegration/selectors';
import { getProjectMetadata } from 'core/dataBus/selectors';
import { getActiveNamespace } from '../../../../core/namespaceIntegration/selectors';
import { getProjectMetadata } from '../../../../core/dataBus/selectors';
import { CONTROLS_KEYS } from 'core/controlsBus/constants';
import { toggleSwitch, fireButtonAction } from 'core/controlsBus/actions';
import { getSwitches, getCheckedState, getDisabledState } from 'core/controlsBus/selectors';
import { CONTROLS_KEYS } from '../../../../core/controlsBus/constants';
import { toggleSwitch, fireButtonAction } from '../../../../core/controlsBus/actions';
import { getSwitches, getCheckedState, getDisabledState } from '../../../../core/controlsBus/selectors';
import ViewSwitchList from './List/ViewSwitchList';
@@ -17,7 +17,7 @@ const mapStateToProps = state => {
: { fullFeaturesSupport: false };
const switches = getSwitches(state);
return {
activeNamespace: namespace,
checkedState: getCheckedState(state),

View File

@@ -1,12 +1,14 @@
import React from 'react';
import { connect } from 'react-redux';
import { Button, Icon } from 'antd';
import Button from 'antd/es/button'
import 'antd/es/button/style'
const ButtonGroup = Button.Group;
import { setZoom } from 'core/controlsBus/actions';
import { getValuesState } from 'core/controlsBus/selectors';
import './index.scss';
import { setZoom } from '../../../../core/controlsBus/actions';
import { getValuesState } from '../../../../core/controlsBus/selectors';
import './index.less';
const ZoomControl = ({ zoom, setZoom }) => {
const step = 0.1;

View File

@@ -1,13 +1,17 @@
import React from 'react';
import { connect } from 'react-redux';
import { Breadcrumb, Icon } from 'antd';
import { FILE_NODE_TYPE } from 'core/constants/index';
import { Copy } from 'components/topBar/controls/Copy/index';
import { getActiveNamespace } from 'core/namespaceIntegration/selectors';
import { getSourceUserChoice, getProjectMetadata } from 'core/dataBus/selectors';
import Icon from 'antd/es/icon'
import 'antd/es/icon/style'
import Breadcrumb from 'antd/es/breadcrumb'
import 'antd/es/breadcrumb/style'
import './SubPanelContainer.scss';
import { FILE_NODE_TYPE } from '../../../core/constants/index';
import { Copy } from '../controls/Copy/index';
import { getActiveNamespace } from '../../../core/namespaceIntegration/selectors';
import { getSourceUserChoice, getProjectMetadata } from '../../../core/dataBus/selectors';
import './SubPanelContainer.less';
const SubPanelContainer = ({ selectedNode, platformPathSeparator }) => {
if (!selectedNode)

View File

@@ -1,5 +1,6 @@
.TreeDiagramsContainer {
overflow: auto;
width: 100%;
}
.MainLoader {

View File

@@ -1,18 +1,19 @@
import React from 'react';
import { connect } from 'react-redux';
import { Spin } from 'antd';
import Spin from 'antd/es/spin';
import 'antd/es/spin/style';
import StandalonePlaceholder from './component/StandalonePlaceholder';
import { getNamespacesList } from 'core/dataBus/selectors';
import { getActiveNamespace } from 'core/namespaceIntegration/selectors';
import { getNamespacesList } from '../../core/dataBus/selectors';
import { getActiveNamespace } from '../../core/namespaceIntegration/selectors';
import TreeDiagram from './component/TreeDiagram';
import './TreeDiagamsContainer.scss';
import './TreeDiagamsContainer.less';
const TreeDiagramsContainer = ({ namespacesList, activeNamespace }) => {
if (!namespacesList.length) {
return process.env.STANDALONE ? (
return !process.env.LOCAL ? (
<StandalonePlaceholder />
) : (
<div className={'MainLoader'}>

View File

@@ -1,18 +1,20 @@
import React from 'react';
import classNames from 'classnames';
import { SYMBOL_WIDTH } from 'components/treeDiagram/component/constants';
import Arrow from 'components/treeDiagram/component/Icons/Arrow';
import './index.scss';
import { SYMBOL_WIDTH } from '../constants';
import Arrow from '../Icons/Arrow';
import './index.less';
const SINGLE_CRUMB_SHIFT = 22;
export const PartEdge = props => {
const { sourcePosition, parentName } = props;
const { sourcePosition, parentName, ccAlightPoint, singleCrumb } = props;
const nameWidth = SYMBOL_WIDTH * parentName.length;
const padding = 17;
const P1 = { x: sourcePosition.x + nameWidth + padding, y: sourcePosition.y };
const P2 = { x: P1.x + padding + 6, y: P1.y };
const P2 = { x: ccAlightPoint - padding - 5 + (singleCrumb ? SINGLE_CRUMB_SHIFT : 0), y: P1.y };
const polylinePoints = [[P1.x, P1.y], [P2.x, P2.y]];
@@ -28,20 +30,16 @@ export const PartEdge = props => {
);
};
export const CodeCrumbEdge = props => {
const { sourcePosition, targetPosition, parentName } = props;
export const CodeCrumbMultiEdge = props => {
const { sourcePosition, targetPosition, ccAlightPoint } = props;
const nameWidth = SYMBOL_WIDTH * parentName.length;
const padding = 40;
const edgeTurnDistance = 20;
const P1 = { x: sourcePosition.x + nameWidth + padding, y: sourcePosition.y };
const P2 = { x: targetPosition.x - edgeTurnDistance, y: sourcePosition.y };
const P3 = { x: targetPosition.x - edgeTurnDistance, y: targetPosition.y };
const edgeTurnDistance = SINGLE_CRUMB_SHIFT;
const xStart = ccAlightPoint || targetPosition.x;
const P2 = { x: xStart - edgeTurnDistance, y: sourcePosition.y };
const P3 = { x: xStart - edgeTurnDistance, y: targetPosition.y };
const P4 = targetPosition;
const polylinePoints = [[P1.x, P1.y], [P2.x, P2.y], [P3.x, P3.y], [P4.x, P4.y]];
const polylinePoints = [[P2.x, P2.y], [P3.x, P3.y], [P4.x, P4.y]];
return (
<polyline points={polylinePoints.join(', ')} className={'CodeCrumbEdge'} strokeDasharray="2" />
@@ -49,23 +47,15 @@ export const CodeCrumbEdge = props => {
};
export const CodeCrumbedFlowEdge = props => {
const {
sourcePosition,
targetPosition,
sourceName,
singleCrumbSource,
singleCrumbTarget,
selected,
onClick
} = props;
const { sourcePosition, targetPosition, sourceName, selected, onClick } = props;
const rHalf = 6;
const sourcePt = {
x: -rHalf + (singleCrumbSource ? sourcePosition.x - 22 : sourcePosition.x),
x: -rHalf + sourcePosition.x,
y: sourcePosition.y + rHalf
};
const targetPt = {
x: -rHalf + (singleCrumbTarget ? targetPosition.x - 22 : targetPosition.x),
x: -rHalf + targetPosition.x,
y: targetPosition.y - rHalf
};
@@ -155,7 +145,7 @@ export const CodeCrumbedFlowEdge = props => {
y={endPointConfig.y}
height={iconSize}
width={iconSize}
fill={selected ? '#754BC3' : '#e91e63'}
fill={selected ? '#754BC3' : '#717070'}
/>
</g>
);
@@ -166,8 +156,6 @@ export const ExternalEdge = props => {
const {
sourcePosition,
targetPosition,
singleCrumbSource,
singleCrumbTarget,
topBottom,
areaHeight,
firstPart,
@@ -177,11 +165,11 @@ export const ExternalEdge = props => {
const rHalf = 6;
const sourcePt = {
x: -rHalf + (singleCrumbSource ? sourcePosition.x - 22 : sourcePosition.x),
x: -rHalf + sourcePosition.x,
y: sourcePosition.y + rHalf
};
const targetPt = {
x: -rHalf + (singleCrumbTarget ? targetPosition.x - 22 : targetPosition.x),
x: -rHalf + targetPosition.x,
y: targetPosition.y - rHalf
};
@@ -231,7 +219,7 @@ export const ExternalEdge = props => {
y={targetPt.y - iconSize}
height={iconSize}
width={iconSize}
fill={selected ? '#754BC3' : '#e91e63'}
fill={selected ? '#754BC3' : '#717070'}
/>
)}
</g>

View File

@@ -1,9 +1,9 @@
import React from 'react';
import classNames from 'classnames';
import { LAYOUT_CONFIG, DepEdgeGroups } from 'components/treeDiagram/component/constants';
import Arrow from 'components/treeDiagram/component/Icons/Arrow';
import './index.scss';
import { LAYOUT_CONFIG, DepEdgeGroups } from '../constants';
import Arrow from '../Icons/Arrow';
import './index.less';
const { TOP_LEFT, TOP_RIGHT } = DepEdgeGroups;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import classNames from 'classnames';
import './index.scss';
import './index.less';
export const SourceEdge = props => {
const { targetPosition, sourcePosition, disabled, singleChild, selected } = props;

View File

@@ -1,4 +1,4 @@
@import "../animcations.scss";
@import "../animcations.less";
.EdgeMouseHandler {
cursor: pointer;
@@ -38,7 +38,7 @@
@extend .FadeIn;
fill: none;
stroke: #ff18a6;
stroke: #8c8b8b;
}
.CodeCrumbEdge-under-flow {
@@ -49,7 +49,7 @@
.CodeCrumbEdge-flow {
fill: none;
stroke: #ff18a6;
stroke: #717070;
}
.CodeCrumbEdge-flow-selected {
@@ -57,8 +57,8 @@
}
.CodeCrumbEdge-flow-source {
fill: #ff18a6;
stroke: #ff18a6;
fill: #717070;
stroke: #717070;
}
.CodeCrumbEdge-flow-source-selected {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import './index.scss';
import './index.less';
const styleUp = {
transform: 'rotate(-90deg)',

View File

@@ -1,6 +1,6 @@
import React from 'react';
import './index.scss';
import './index.less';
export default ({ position, selected }) => {
return (

View File

@@ -1,6 +1,6 @@
import React from 'react';
import './index.scss';
import './index.less';
export const OpenFolder = ({ x, y, width, height, fill }) => (
<svg

View File

@@ -1,4 +1,4 @@
@import "../animcations.scss";
@import "../animcations.less";
.Animation {
@extend .FadeIn;

View File

@@ -1,8 +1,7 @@
import React from 'react';
import classNames from 'classnames';
import './index.scss';
import { SYMBOL_WIDTH } from 'components/treeDiagram/component/constants';
import './index.less';
export const CodeCrumbName = props => {
// onMouseOver maybe use onMouseOver to show crumb details in popover
@@ -19,7 +18,7 @@ export const CodeCrumbName = props => {
onClick
} = props;
const textPoint = { x: singleCrumb ? position.x - 22 : position.x, y: position.y };
const textPoint = position;
const symbolWidth = 6;
const locWidth = loc.length ? loc.length * symbolWidth + 3 : 0;

View File

@@ -1,15 +1,15 @@
import React from 'react';
import classNames from 'classnames';
import { SYMBOL_WIDTH } from 'components/treeDiagram/component/constants';
import { SYMBOL_WIDTH, NODE_NAME_X_SHIFT } from '../constants';
import FileIcon from 'components/treeDiagram/component/Icons/language/File';
import CppFileIcon from 'components/treeDiagram/component/Icons/language/CppFile';
import JavaScriptFileIcon from 'components/treeDiagram/component/Icons/language/JavaScriptFile';
import PythonFileIcon from 'components/treeDiagram/component/Icons/language/PythonFile';
import FileIcon from '../Icons/language/File';
import CppFileIcon from '../Icons/language/CppFile';
import JavaScriptFileIcon from '../Icons/language/JavaScriptFile';
import PythonFileIcon from '../Icons/language/PythonFile';
import DepCirclesIcon from 'components/treeDiagram/component/Icons/DepCircles';
import './index.scss';
import DepCirclesIcon from '../Icons/DepCircles';
import './index.less';
const getFileIcon = ({ position, iconSize, language }) => {
switch (language) {
@@ -85,12 +85,12 @@ export const FileName = props => {
<rect
x={position.x + 3}
y={position.y - 3}
width={16}
width={NODE_NAME_X_SHIFT}
height={5}
className={'NodeText-cover'}
/>
<rect
x={position.x + 16}
x={position.x + NODE_NAME_X_SHIFT}
y={position.y - 8}
width={nameWidth}
height={16}
@@ -112,7 +112,7 @@ export const FileName = props => {
<g>
<title>{path}</title>
<text
x={position.x + 16}
x={position.x + NODE_NAME_X_SHIFT}
y={position.y + 5}
className={classNames('NodeText-file-name', {
'NodeText-file-name-purple': purple,

View File

@@ -1,13 +1,13 @@
import React from 'react';
import classNames from 'classnames';
import { FOLDER_OPEN_STATE } from 'core/constants';
import { FOLDER_OPEN_STATE } from '../../../../core/constants';
import {
OpenFolder as OpenFolderIcon,
CloseFolder as CloseFolderIcon
} from 'components/treeDiagram/component/Icons/Folder';
} from '../Icons/Folder';
import './index.scss';
import { SYMBOL_WIDTH } from 'components/treeDiagram/component/constants';
import './index.less';
import { SYMBOL_WIDTH } from '../constants';
export const FolderName = props => {
const { position, name, cover, disabled, openedState, onNodeClick } = props;

View File

@@ -1,4 +1,4 @@
@import "../animcations.scss";
@import "../animcations.less";
.CodeCrumbNode {
@extend .FadeIn;
@@ -76,7 +76,7 @@
.CodeCrumbName-flow-step {
fill: #ff18a6;
stroke: #e91e63;
stroke: #ff18a6;
}
.CodeCrumbName-flow-step-selected {

View File

@@ -1,9 +1,13 @@
import React from 'react';
import { connect } from 'react-redux';
import { Upload, Icon } from 'antd';
import { uploadStore } from 'core/dataBus/actions';
import './index.scss';
import Upload from 'antd/es/upload'
import 'antd/es/upload/style'
import Icon from 'antd/es/icon'
import 'antd/es/icon/style'
import { uploadStore } from '../../../../core/dataBus/actions';
import './index.less';
const Dragger = Upload.Dragger;

View File

@@ -1,94 +0,0 @@
import React from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import { getCheckedState } from 'core/controlsBus/selectors';
import { getCodeCrumbsUserChoice, getSourceLayout } from 'core/dataBus/selectors';
import { isCodeCrumbSelected } from '../helpers';
import './index.scss';
const DetailsComponent = props => {
const { name, details, position, singleCrumb, selected } = props;
// TODO: refactor
const nameWidth = name ? name.length * 7.5 : 100;
return (
<div
className={classNames('CcDetailsContainer', { CcDetailsSelected: selected })}
style={{
left: position.x - (singleCrumb ? 20 : 0),
top: position.y + 8,
width: nameWidth + 'px'
}}
>
{details}
</div>
);
};
const DetailsSet = ({
detailsEnabled,
codecrumbsLayoutMap,
shiftToCenterPoint,
selectedCrumbedFlowKey,
selectedCcFlowEdgeNodes
}) => {
if (!detailsEnabled) return null;
const detailsPanels = [];
Object.keys(codecrumbsLayoutMap).forEach(filePath => {
const codecrumbs = (codecrumbsLayoutMap[filePath].children || [])
.filter(({ data }) => data.params.flow === selectedCrumbedFlowKey)
.map(({ data, x, y }) => ({
name: data.name,
details: data.params.details,
filePath,
x,
y
}));
codecrumbs.forEach((ccNode, i) => {
if (!ccNode || !ccNode.details) {
return null;
}
const [nX, nY] = [ccNode.y, ccNode.x];
const position = shiftToCenterPoint(nX, nY);
detailsPanels.push(
<DetailsComponent
key={filePath + i}
details={ccNode.details}
name={ccNode.name}
position={position}
selected={isCodeCrumbSelected(selectedCcFlowEdgeNodes, ccNode)}
singleCrumb={codecrumbs.length === 1}
/>
);
});
});
return <React.Fragment>{detailsPanels}</React.Fragment>;
};
const mapStateToProps = (state, props) => {
const { codeCrumbsMinimize, codeCrumbsDetails } = getCheckedState(state);
const { namespace } = props;
const namespaceProps = { namespace };
const { codecrumbsLayoutMap } = getSourceLayout(state, namespaceProps);
const { selectedCrumbedFlowKey, selectedCcFlowEdgeNodes } = getCodeCrumbsUserChoice(
state,
namespaceProps
);
return {
codecrumbsLayoutMap,
selectedCrumbedFlowKey,
detailsEnabled: !codeCrumbsMinimize && codeCrumbsDetails,
selectedCcFlowEdgeNodes
};
};
export default connect(mapStateToProps)(DetailsSet);

View File

@@ -0,0 +1,142 @@
import React, { Suspense } from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import { getCheckedState } from '../../../../../../core/controlsBus/selectors';
import {
getCodeCrumbsUserChoice,
getSourceLayout,
getProjectMetadata
} from '../../../../../../core/dataBus/selectors';
import { getCcPosition, isCodeCrumbSelected } from '../helpers';
import './index.less';
const Code = React.lazy(() =>
import(/* webpackChunkName: "code" */ '../../../../../sideBar/component/Code')
);
const DetailsComponent = props => {
const { name, details, position, selected } = props;
const nameWidth = name ? name.length * 7.5 : 100;
return (
<div
className={classNames('CcDetailsContainer', { CcDetailsSelected: selected })}
style={{
left: position.x,
top: position.y,
width: nameWidth + 'px'
}}
>
{details}
</div>
);
};
const CodeComponent = props => {
const { position, crumbNodeLines, file, language, namespace } = props;
const { fileCode } = file.data;
return (
<div
className={'CcCodeContainer'}
style={{
left: position.x,
top: position.y
}}
>
<Suspense fallback={null}>
<Code
namespace={namespace}
language={language}
code={fileCode}
fontSize={10}
lineHeight={15}
crumbedLines={[crumbNodeLines]}
/>
</Suspense>
</div>
);
};
const ExtraInfoSet = ({
detailsEnabled,
codePreviewEnabled,
shiftToCenterPoint,
ccAlightPoint,
selectedCcFlowEdgeNodes,
flowSteps,
sortedFlowSteps,
filesLayoutMap,
ccShiftIndexMap,
namespace,
language
}) => {
if (!detailsEnabled && !codePreviewEnabled) return null;
const crumbs = sortedFlowSteps.length ? sortedFlowSteps : flowSteps;
return (
<React.Fragment>
{crumbs.map(crumb => {
if (crumb.namespace !== namespace) {
return null;
}
const [_, nY] = [crumb.y, crumb.x];
const position = shiftToCenterPoint(
getCcPosition(ccAlightPoint, ccShiftIndexMap[crumb.id]),
nY + 8
);
if (detailsEnabled && crumb.params && crumb.params.details) {
return (
<DetailsComponent
key={crumb.id}
details={crumb.params.details}
name={crumb.name}
position={position}
selected={isCodeCrumbSelected(selectedCcFlowEdgeNodes, crumb)}
/>
);
}
if (codePreviewEnabled) {
return (
<CodeComponent
key={crumb.id}
position={position}
crumbNodeLines={crumb.crumbNodeLines}
file={filesLayoutMap[crumb.filePath]}
namespace={namespace}
language={language}
/>
);
}
return null;
})}
</React.Fragment>
);
};
const mapStateToProps = (state, props) => {
const { codeCrumbsMinimize, codeCrumbsDetails, codeCrumbsCodePreview } = getCheckedState(state);
const { namespace } = props;
const namespaceProps = { namespace };
const { language } = getProjectMetadata(state, namespaceProps);
const { selectedCcFlowEdgeNodes } = getCodeCrumbsUserChoice(state, namespaceProps);
const { ccAlightPoint, filesLayoutMap } = getSourceLayout(state, namespaceProps);
return {
detailsEnabled: !codeCrumbsMinimize && codeCrumbsDetails,
codePreviewEnabled: !codeCrumbsMinimize && codeCrumbsCodePreview,
filesLayoutMap,
selectedCcFlowEdgeNodes,
ccAlightPoint,
language
};
};
export default connect(mapStateToProps)(ExtraInfoSet);

View File

@@ -1,8 +1,7 @@
.CcDetailsContainer {
position: absolute;
border: 1px solid #e8e8e8;
border-top: 1px solid #ff18a6;
min-width: 150px;
min-width: 250px;
background: rgba(255,255,255,0.9);
font-size: 12px;
padding: 6px 7px;
@@ -11,4 +10,12 @@
.CcDetailsSelected {
border-top: 1px solid #754BC3;
}
}
.CcCodeContainer {
position: absolute;
border: 1px solid #e8e8e8;
width: 650px;
background: rgba(255,255,255,0.9);
height: 80px;
}

View File

@@ -1,31 +1,27 @@
import React from 'react';
import { connect } from 'react-redux';
import {
CodeCrumbedFlowEdge,
ExternalEdge
} from 'components/treeDiagram/component/Edge/CodeCrumbEdge';
} from '../../../component/Edge/CodeCrumbEdge';
import { isCodeCrumbsEqual, getCcPosition } from './helpers';
import { getCheckedState } from 'core/controlsBus/selectors';
import { getNamespacesList, getCodeCrumbsUserChoice } from 'core/dataBus/selectors';
import { selectCcFlowEdge } from 'core/dataBus/actions';
import { isCodeCrumbsEqual, gatherFlowStepsData } from './helpers';
const FlowEdge = props => {
export default props => {
const {
namespace,
areaHeight,
namespacesList,
shiftToCenterPoint,
ccShiftIndexMap,
sortedFlowSteps,
ccFilesLayoutMapNs,
involvedNsData,
codeCrumbsMinimize,
onFlowEdgeClick,
selectedCcFlowEdgeNodes
} = props;
const codecrumbsLayoutMap = ccFilesLayoutMapNs[namespace];
const ccNamespacesKeys = Object.keys(ccFilesLayoutMapNs || {});
const { codecrumbsLayoutMap } = involvedNsData[namespace];
const ccNamespacesKeys = Object.keys(involvedNsData || {});
return (
<React.Fragment>
@@ -39,8 +35,9 @@ const FlowEdge = props => {
}
const edgePoints = [fromItem, toItem].map(crumb => {
const [cX, cY] = [crumb.y, crumb.x];
return shiftToCenterPoint(cX, cY);
const [_, cY] = [crumb.y, crumb.x];
const { ccAlightPoint } = involvedNsData[crumb.namespace];
return shiftToCenterPoint(getCcPosition(ccAlightPoint, ccShiftIndexMap[crumb.id]), cY);
});
const edgeBaseProps = {
@@ -55,7 +52,7 @@ const FlowEdge = props => {
if (fromItem.namespace === namespace && toItem.namespace !== namespace) {
const fromFile = codecrumbsLayoutMap[fromItem.filePath];
const toFile = ccFilesLayoutMapNs[toItem.namespace][toItem.filePath];
const toFile = involvedNsData[toItem.namespace].codecrumbsLayoutMap[toItem.filePath];
return (
<ExternalEdge
@@ -70,7 +67,8 @@ const FlowEdge = props => {
}
if (fromItem.namespace !== namespace && toItem.namespace === namespace) {
const fromFile = ccFilesLayoutMapNs[fromItem.namespace][fromItem.filePath];
const fromFile =
involvedNsData[fromItem.namespace].codecrumbsLayoutMap[fromItem.filePath];
const toFile = codecrumbsLayoutMap[toItem.filePath];
return (
@@ -107,52 +105,3 @@ const isFlowEdgeSelected = (selectedCcFlowEdgeNodes, currentSource, currentTarge
const { source, target } = selectedCcFlowEdgeNodes;
return isCodeCrumbsEqual(source, currentSource) && isCodeCrumbsEqual(target, currentTarget);
};
const mapStateToProps = (state, props) => {
const { codeCrumbsMinimize } = getCheckedState(state);
const namespacesList = getNamespacesList(state);
const { namespace } = props;
const {
selectedCrumbedFlowKey: currentSelectedCrumbedFlowKey,
selectedCcFlowEdgeNodes
} = getCodeCrumbsUserChoice(state, {
namespace
});
const gatheredFlowsData = gatherFlowStepsData({
currentSelectedCrumbedFlowKey,
namespacesList,
state
});
return {
namespacesList,
codeCrumbsMinimize,
selectedCcFlowEdgeNodes,
...gatheredFlowsData
};
};
// TODO: can be moved to action
const mapDispatchToProps = dispatch => ({
onFlowEdgeClick: (source, target, ccNamespacesKeys) => {
dispatch(selectCcFlowEdge({ source, target }, source.namespace));
// case with external edge
if (source.namespace !== target.namespace) {
dispatch(selectCcFlowEdge({ source, target }, target.namespace));
}
ccNamespacesKeys.forEach(ns => {
if (ns !== source.namespace && ns !== target.namespace) {
dispatch(selectCcFlowEdge(undefined, ns));
}
});
}
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(FlowEdge);

View File

@@ -1,20 +1,18 @@
import React from 'react';
import { NO_TRAIL_FLOW } from 'core/constants';
import { CodeCrumbName } from 'components/treeDiagram/component/Node/CodeCrumb';
import { FileName } from 'components/treeDiagram/component/Node/File';
import { PartEdge, CodeCrumbEdge } from 'components/treeDiagram/component/Edge/CodeCrumbEdge';
import { isCodeCrumbSelected } from './helpers';
import { NO_TRAIL_FLOW } from '../../../../../core/constants';
import { CodeCrumbName } from '../../../../treeDiagram/component/Node/CodeCrumb';
import { PartEdge, CodeCrumbMultiEdge } from '../../../../treeDiagram/component/Edge/CodeCrumbEdge';
import { isCodeCrumbSelected, getCcPosition } from './helpers';
const Tree = props => {
const {
language,
ccAlightPoint,
ccShiftIndexMap,
shiftToCenterPoint,
codecrumbsLayoutMap,
filesMap,
selectedCrumbedFlowKey,
sourceDiagramOn,
dependenciesDiagramOn,
currentSelectedCrumbedFlowKey,
codeCrumbsMinimize,
codeCrumbsLineNumbers,
onCodeCrumbSelect,
@@ -30,39 +28,49 @@ const Tree = props => {
const position = shiftToCenterPoint(nX, nY);
const file = filesMap[node.data.path];
const singleCrumb = node.children.length === 1;
const firstCrumbXPoint =
!singleCrumb &&
shiftToCenterPoint(
currentSelectedCrumbedFlowKey !== NO_TRAIL_FLOW
? getCcPosition(ccAlightPoint, ccShiftIndexMap[node.children[0].data.id])
: ccAlightPoint,
node.children[0].y
).x;
return (
<React.Fragment key={`code-crumb-${node.data.path}-${key}`}>
{!sourceDiagramOn && !dependenciesDiagramOn ? (
<FileName
language={language}
position={position}
name={file.name}
purple={codeCrumbsMinimize}
/>
) : null}
{(!codeCrumbsMinimize && (
<PartEdge sourcePosition={position} parentName={file.name} />
)) ||
null}
{!codeCrumbsMinimize &&
node.children.map((crumb, i, list) => {
const [cX, cY] = [crumb.y, crumb.x];
const crumbPosition = shiftToCenterPoint(cX, cY);
const singleCrumb = list.length === 1;
node.children.map((crumb, i) => {
const [_, cY] = [crumb.y, crumb.x];
const crumbData = crumb.data;
const crumbPosition = shiftToCenterPoint(
currentSelectedCrumbedFlowKey !== NO_TRAIL_FLOW
? getCcPosition(ccAlightPoint, ccShiftIndexMap[crumbData.id])
: ccAlightPoint,
cY
);
const ccParams = crumbData.params;
return (
<React.Fragment key={`code-crumb-edge-${file.path}-${crumbData.name}`}>
{(!singleCrumb && (
<CodeCrumbEdge
{!i && (
<PartEdge
sourcePosition={position}
parentName={file.name}
ccAlightPoint={crumbPosition.x}
singleCrumb={singleCrumb}
/>
)}
{!singleCrumb && (
<CodeCrumbMultiEdge
sourcePosition={position}
targetPosition={crumbPosition}
parentName={file.name}
ccAlightPoint={i && firstCrumbXPoint}
/>
)) ||
null}
)}
<CodeCrumbName
position={crumbPosition}
loc={codeCrumbsLineNumbers ? crumbData.displayLoc : ''}
@@ -72,8 +80,8 @@ const Tree = props => {
selected={isCodeCrumbSelected(selectedCcFlowEdgeNodes, crumbData)}
flow={
ccParams.flow &&
ccParams.flow === selectedCrumbedFlowKey &&
selectedCrumbedFlowKey !== NO_TRAIL_FLOW
ccParams.flow === currentSelectedCrumbedFlowKey &&
currentSelectedCrumbedFlowKey !== NO_TRAIL_FLOW
}
flowStep={ccParams.flowStep}
onClick={e => onCodeCrumbSelect(e, { fileNode: file, codeCrumb: crumbData })}

View File

@@ -1,5 +1,5 @@
import { getCodeCrumbsUserChoice, getSourceLayout } from 'core/dataBus/selectors';
import { NO_TRAIL_FLOW } from 'core/constants';
import { getCodeCrumbsUserChoice, getSourceLayout } from '../../../../../core/dataBus/selectors';
import { NO_TRAIL_FLOW } from '../../../../../core/constants';
export const isCodeCrumbsEqual = (cc, currentCc) =>
cc.name === currentCc.name && cc.flowStep === currentCc.flowStep;
@@ -15,17 +15,15 @@ export const isCodeCrumbSelected = (selectedCcFlowEdgeNodes, cc) => {
const stepSorter = (a, b) => a.step - b.step;
// TODO: this should be done in reducer ?
const getSortedFlowSteps = ({
const getFlowSteps = ({
namespace,
codeCrumbedFlowsMap,
selectedCrumbedFlowKey,
codecrumbsLayoutMap
}) => {
const currentFlow = codeCrumbedFlowsMap[selectedCrumbedFlowKey] || {};
let sortedFlowSteps = [];
Object.keys(currentFlow).forEach(filePath => {
return Object.keys(currentFlow).reduce((flowSteps, filePath) => {
const steps = ((codecrumbsLayoutMap[filePath] && codecrumbsLayoutMap[filePath].children) || [])
.filter(({ data }) => data.params.flow === selectedCrumbedFlowKey)
.map(({ data, x, y }) => ({
@@ -38,16 +36,32 @@ const getSortedFlowSteps = ({
y
}));
sortedFlowSteps = sortedFlowSteps.concat(steps);
});
sortedFlowSteps.sort(stepSorter);
return sortedFlowSteps;
return [...flowSteps, ...steps];
}, []);
};
export const gatherFlowStepsData = ({ namespacesList, currentSelectedCrumbedFlowKey, state }) =>
namespacesList.reduce(
const createCcShiftIndexMap = sortedFlowSteps => {
const ccMap = {};
let shiftOrderIndex = 0;
sortedFlowSteps.forEach((crumb, i, list) => {
if (!i) {
ccMap[crumb.id] = shiftOrderIndex;
return;
}
if (crumb.x < list[i - 1].x) {
shiftOrderIndex++;
}
ccMap[crumb.id] = shiftOrderIndex;
});
return ccMap;
};
export const gatherFlowStepsData = (state, { namespacesList, currentSelectedCrumbedFlowKey }) => {
const flowStepsData = namespacesList.reduce(
(acc, ns) => {
const namespaceProps = { namespace: ns };
const { selectedCrumbedFlowKey, codeCrumbedFlowsMap } = getCodeCrumbsUserChoice(
@@ -59,25 +73,40 @@ export const gatherFlowStepsData = ({ namespacesList, currentSelectedCrumbedFlow
return acc;
}
const { codecrumbsLayoutMap } = getSourceLayout(state, namespaceProps);
const { codecrumbsLayoutMap, ccAlightPoint } = getSourceLayout(state, namespaceProps);
const sortedFlowSteps =
selectedCrumbedFlowKey !== NO_TRAIL_FLOW
? getSortedFlowSteps({
namespace: ns,
codeCrumbedFlowsMap,
selectedCrumbedFlowKey,
codecrumbsLayoutMap
})
: [];
const flowSteps = getFlowSteps({
namespace: ns,
codeCrumbedFlowsMap,
selectedCrumbedFlowKey,
codecrumbsLayoutMap
});
return {
sortedFlowSteps: [...acc.sortedFlowSteps, ...sortedFlowSteps].sort(stepSorter),
ccFilesLayoutMapNs: {
...acc.ccFilesLayoutMapNs,
[ns]: codecrumbsLayoutMap
flowSteps,
sortedFlowSteps:
selectedCrumbedFlowKey !== NO_TRAIL_FLOW
? [...acc.sortedFlowSteps, ...flowSteps].sort(stepSorter)
: [],
involvedNsData: {
...acc.involvedNsData,
[ns]: { codecrumbsLayoutMap, ccAlightPoint }
}
};
},
{ ccFilesLayoutMapNs: {}, sortedFlowSteps: [] }
{ involvedNsData: {}, flowSteps: [], sortedFlowSteps: [] }
);
return {
...flowStepsData,
ccShiftIndexMap: createCcShiftIndexMap(flowStepsData.sortedFlowSteps)
};
};
export const getCcPosition = (x, index = 0) => x + 70 * index;
export const getMaxWidthForNs = (state, { namespacesList }) =>
namespacesList.reduce((maxWidth, namespace) => {
const { layoutSize } = getSourceLayout(state, { namespace });
return layoutSize && layoutSize.width > maxWidth ? layoutSize.width : maxWidth;
}, 0);

View File

@@ -1,38 +1,43 @@
import React from 'react';
import { connect } from 'react-redux';
import { selectCodeCrumb, selectNodeToOpenInEditor } from 'core/dataBus/actions';
import { getSource, getSourceLayout, getCodeCrumbsUserChoice } from 'core/dataBus/selectors';
import { getCheckedState } from 'core/controlsBus/selectors';
import {
getSource,
getSourceLayout,
getCodeCrumbsUserChoice,
getNamespacesList
} from '../../../../../core/dataBus/selectors';
import { selectCodeCrumb, selectNodeToOpenInEditor, selectCcFlowEdge } from '../../../../../core/dataBus/actions';
import { getCheckedState } from '../../../../../core/controlsBus/selectors';
import Tree from './Tree';
import FlowEdges from './FlowEdge';
const mapStateToProps = (state, props) => {
const {
sourceDiagramOn,
dependenciesDiagramOn,
codeCrumbsDiagramOn,
codeCrumbsMinimize,
codeCrumbsLineNumbers
} = getCheckedState(state);
const { codeCrumbsMinimize, codeCrumbsLineNumbers } = getCheckedState(state);
const namespacesList = getNamespacesList(state);
const { namespace } = props;
const namespaceProps = { namespace };
const { filesMap } = getSource(state, namespaceProps);
const { codecrumbsLayoutMap } = getSourceLayout(state, namespaceProps);
const { selectedCrumbedFlowKey, selectedCcFlowEdgeNodes } = getCodeCrumbsUserChoice(
state,
namespaceProps
);
const { codecrumbsLayoutMap, ccAlightPoint } = getSourceLayout(state, { namespace });
const {
selectedCrumbedFlowKey: currentSelectedCrumbedFlowKey,
selectedCcFlowEdgeNodes
} = getCodeCrumbsUserChoice(state, {
namespace
});
return {
codecrumbsLayoutMap,
ccAlightPoint,
filesMap,
selectedCrumbedFlowKey,
sourceDiagramOn,
dependenciesDiagramOn,
codeCrumbsDiagramOn,
codeCrumbsMinimize,
currentSelectedCrumbedFlowKey,
codeCrumbsLineNumbers,
namespacesList,
codeCrumbsMinimize,
selectedCcFlowEdgeNodes
};
};
@@ -41,7 +46,7 @@ const mapDispatchToProps = (dispatch, props) => {
const { namespace } = props;
return {
onCodeCrumbSelect: (event, options) => {
return event.metaKey
return event.metaKey || event.altKey
? dispatch(
selectNodeToOpenInEditor(
{ path: options.fileNode.path, line: options.codeCrumb.crumbNodeLines[0] },
@@ -49,6 +54,20 @@ const mapDispatchToProps = (dispatch, props) => {
)
)
: dispatch(selectCodeCrumb(options, namespace));
},
onFlowEdgeClick: (source, target, ccNamespacesKeys) => {
dispatch(selectCcFlowEdge({ source, target }, source.namespace));
// case with external edge
if (source.namespace !== target.namespace) {
dispatch(selectCcFlowEdge({ source, target }, target.namespace));
}
ccNamespacesKeys.forEach(ns => {
if (ns !== source.namespace && ns !== target.namespace) {
dispatch(selectCcFlowEdge(undefined, ns));
}
});
}
};
};
@@ -56,4 +75,11 @@ const mapDispatchToProps = (dispatch, props) => {
export default connect(
mapStateToProps,
mapDispatchToProps
)(Tree);
)(props => {
return (
<React.Fragment>
<FlowEdges {...props} />
<Tree {...props} />
</React.Fragment>
);
});

View File

@@ -4,15 +4,15 @@ import { connect } from 'react-redux';
import {
DependenciesEdge,
DependenciesArrow
} from 'components/treeDiagram/component/Edge/DepenenciesEdge';
import { FileName } from 'components/treeDiagram/component/Node/File';
import { selectDependencyEdge } from 'core/dataBus/actions';
} from '../../Edge/DepenenciesEdge';
import { FileName } from '../../../component/Node/File';
import { selectDependencyEdge } from '../../../../../core/dataBus/actions';
import {
getSourceLayout,
getSourceUserChoice,
getDependenciesUserChoice
} from 'core/dataBus/selectors';
import { getCheckedState } from 'core/controlsBus/selectors';
} from '../../../../../core/dataBus/selectors';
import { getCheckedState } from '../../../../../core/controlsBus/selectors';
import { getGroupsAroundNode, checkIsEdgeSelected } from './utils';

View File

@@ -1,4 +1,4 @@
import { DepEdgeGroups } from 'components/treeDiagram/component/constants';
import { DepEdgeGroups } from '../../../component/constants';
export const getGroupsAroundNode = (moduleNode, importedNodes) => {
const groups = {

View File

@@ -1,14 +1,13 @@
import React from 'react';
import { FILE_NODE_TYPE, DIR_NODE_TYPE } from 'core/constants';
import { FileName } from 'components/treeDiagram/component/Node/File';
import { FolderName } from 'components/treeDiagram/component/Node/Folder';
import Dot from 'components/treeDiagram/component/Icons/Dot';
import { SourceEdge } from 'components/treeDiagram/component/Edge/SourceEdge';
import { FILE_NODE_TYPE, DIR_NODE_TYPE } from '../../../../../core/constants';
import { FileName } from '../../Node/File';
import { FolderName } from '../../Node/Folder';
import Dot from '../../Icons/Dot';
import { SourceEdge } from '../../Edge/SourceEdge';
import DependenciesTree from '../Dependencies/index';
import CodeCrumbsTree from '../CodeCrumbs/';
import CodeCrumbedFlowEdges from '../CodeCrumbs/FlowEdge';
const SourceTree = props => {
const {
@@ -20,6 +19,9 @@ const SourceTree = props => {
sourceDimFolders,
codeCrumbsDiagramOn,
codeCrumbsMinimize,
sortedFlowSteps,
involvedNsData,
ccShiftIndexMap,
areaHeight,
sourceLayoutTree,
@@ -140,15 +142,6 @@ const SourceTree = props => {
/>
)}
{(codeCrumbsDiagramOn && (
<CodeCrumbedFlowEdges
namespace={namespace}
shiftToCenterPoint={shiftToCenterPoint}
areaHeight={areaHeight}
/>
)) ||
null}
{(sourceDiagramOn && sourceNodes) || null}
{(sourceDiagramOn && sourceDotes) || null}
@@ -157,6 +150,10 @@ const SourceTree = props => {
namespace={namespace}
language={language}
shiftToCenterPoint={shiftToCenterPoint}
sortedFlowSteps={sortedFlowSteps}
involvedNsData={involvedNsData}
ccShiftIndexMap={ccShiftIndexMap}
areaHeight={areaHeight}
/>
)) ||
null}

View File

@@ -1,15 +1,15 @@
import React from 'react';
import { connect } from 'react-redux';
import { selectNode, selectNodeToOpenInEditor, toggleFolder } from 'core/dataBus/actions';
import { selectNode, selectNodeToOpenInEditor, toggleFolder } from '../../../../../core/dataBus/actions';
import {
getSource,
getSourceLayout,
getSourceUserChoice,
getDependenciesUserChoice,
getProjectMetadata
} from 'core/dataBus/selectors';
import { getCheckedState } from 'core/controlsBus/selectors';
} from '../../../../../core/dataBus/selectors';
import { getCheckedState } from '../../../../../core/controlsBus/selectors';
import SourceTree from './Tree';
const mapStateToProps = (state, props) => {
@@ -56,7 +56,7 @@ const mapDispatchToProps = (dispatch, props) => {
event.preventDefault();
event.stopPropagation();
return event.metaKey
return event.metaKey || event.altKey
? dispatch(selectNodeToOpenInEditor(fileNode, namespace))
: dispatch(selectNode(fileNode, namespace));
},

View File

@@ -2,19 +2,22 @@ import React from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import Draggable from 'react-draggable';
import SourceTree from './Tree/Source/';
import CodeCrumbsDetails from './Tree/CodeCrumbs/Details';
import CodeCrumbsExtraInfo from './Tree/CodeCrumbs/ExtraInfo';
import { UnderLayer } from './UnderLayer';
import './TreeDiagram.scss';
import './TreeDiagram.less';
import { buildShiftToPoint } from 'core/dataBus/utils/geometry';
import { getSourceLayout, getProjectMetadata } from 'core/dataBus/selectors';
import { getCheckedState, getValuesState } from 'core/controlsBus/selectors';
import { calculateLayoutSize } from 'core/dataBus/utils/geometry';
import { selectDependencyEdge, selectCcFlowEdge } from 'core/dataBus/actions';
import { setActiveNamespace } from 'core/namespaceIntegration/actions';
import { buildShiftToPoint } from '../../../core/dataBus/utils/geometry';
import {
getProjectMetadata,
getSourceLayout,
getCodeCrumbsUserChoice,
getNamespacesList
} from '../../../core/dataBus/selectors';
import { getCheckedState, getValuesState } from '../../../core/controlsBus/selectors';
import { selectDependencyEdge, selectCcFlowEdge } from '../../../core/dataBus/actions';
import { setActiveNamespace } from '../../../core/namespaceIntegration/actions';
import { gatherFlowStepsData, getMaxWidthForNs } from './Tree/CodeCrumbs/helpers';
class TreeDiagram extends React.Component {
render() {
@@ -27,15 +30,20 @@ class TreeDiagram extends React.Component {
active,
diagramZoom,
layoutSize,
maxWidth,
sourceLayoutTree,
onUnderLayerClick
onUnderLayerClick,
flowSteps,
sortedFlowSteps,
involvedNsData,
ccShiftIndexMap
} = this.props;
const { width, height, xShift, yShift, bounds } = layoutSize;
if (!width && !height) {
if (!layoutSize) {
return null;
}
const { width, height, xShift, yShift } = layoutSize;
const shiftToCenterPoint = buildShiftToPoint({
x: xShift,
y: yShift
@@ -52,30 +60,35 @@ class TreeDiagram extends React.Component {
{projectName}
</p>
) : null}
<Draggable bounds={bounds} disabled={true}>
<div>
<svg
width={width}
height={height}
xmlns="http://www.w3.org/2000/svg"
shapeRendering="optimizeSpeed"
>
{sourceLayoutTree && (
<React.Fragment>
<UnderLayer width={width} height={height} onClick={onUnderLayerClick} />
<SourceTree
namespace={namespace}
shiftToCenterPoint={shiftToCenterPoint}
areaHeight={height}
/>
</React.Fragment>
)}
</svg>
{codeCrumbsDiagramOn ? (
<CodeCrumbsDetails namespace={namespace} shiftToCenterPoint={shiftToCenterPoint} />
) : null}
</div>
</Draggable>
<svg
width={maxWidth || width}
height={height}
xmlns="http://www.w3.org/2000/svg"
shapeRendering="optimizeSpeed"
>
{sourceLayoutTree && (
<React.Fragment>
<UnderLayer width={maxWidth || width} height={height} onClick={onUnderLayerClick} />
<SourceTree
namespace={namespace}
shiftToCenterPoint={shiftToCenterPoint}
areaHeight={height}
sortedFlowSteps={sortedFlowSteps}
involvedNsData={involvedNsData}
ccShiftIndexMap={ccShiftIndexMap}
/>
</React.Fragment>
)}
</svg>
{codeCrumbsDiagramOn ? (
<CodeCrumbsExtraInfo
namespace={namespace}
shiftToCenterPoint={shiftToCenterPoint}
ccShiftIndexMap={ccShiftIndexMap}
sortedFlowSteps={sortedFlowSteps}
flowSteps={flowSteps}
/>
) : null}
</div>
);
}
@@ -83,18 +96,49 @@ class TreeDiagram extends React.Component {
const mapStateToProps = (state, props) => {
const { namespace } = props;
const { sourceLayoutTree } = getSourceLayout(state, { namespace });
const { sourceLayoutTree, layoutSize } = getSourceLayout(state, { namespace });
if (!sourceLayoutTree) {
return {};
}
const { projectName } = getProjectMetadata(state, { namespace });
const { diagramZoom } = getValuesState(state);
const { codeCrumbsDiagramOn } = getCheckedState(state);
let extendedCcProps = {};
if (codeCrumbsDiagramOn) {
const codeCrumbsUserChoice = getCodeCrumbsUserChoice(state, {
namespace
});
const namespacesList = getNamespacesList(state);
const { flowSteps, sortedFlowSteps, involvedNsData, ccShiftIndexMap } = gatherFlowStepsData(
state,
{
currentSelectedCrumbedFlowKey: codeCrumbsUserChoice.selectedCrumbedFlowKey,
namespacesList
}
);
const maxWidth = getMaxWidthForNs(state, { namespacesList });
extendedCcProps = {
flowSteps,
sortedFlowSteps,
involvedNsData,
ccShiftIndexMap,
maxWidth
};
}
return {
namespace,
projectName,
codeCrumbsDiagramOn,
diagramZoom,
sourceLayoutTree,
layoutSize: calculateLayoutSize(sourceLayoutTree)
layoutSize,
...extendedCcProps
};
};

View File

@@ -1,6 +1,6 @@
import React from 'react';
import './index.scss';
import './index.less';
export const UnderLayer = props => {
const { width, height, onClick } = props;

View File

@@ -2,6 +2,7 @@ export const PURPLE_COLOR = '#ff18a6';
export const BLUE_COLOR = '#1890ff';
export const SYMBOL_WIDTH = 8.4;
export const NODE_NAME_X_SHIFT = 16;
export const LAYOUT_CONFIG = {
symbolWidth: SYMBOL_WIDTH,

Some files were not shown because too many files have changed in this diff Show More