├── .DS_Store
├── .babelrc
├── .dockerignore
├── .editorconfig
├── .env
├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .gitmodules
├── .travis.yml
├── Dockerfile
├── Dockerfile.release
├── LICENSE.md
├── README.md
├── dist
├── .DS_Store
├── 0f93a6be147210993def.worker.js
├── 0f93a6be147210993def.worker.js.map
├── 448c34a56d699c29117adc64c43affeb.woff2
├── 4541e467a38a4b63e624.worker.js
├── 4541e467a38a4b63e624.worker.js.map
├── 500bad5c320fac984203.worker.js
├── 500bad5c320fac984203.worker.js.map
├── 674f50d287a8c48dc19ba404d20fe713.eot
├── 89889688147bd7575d6327160d64e760.svg
├── 912ec66d7572ff821749319396470bde.svg
├── abf5abd2bbdc4ae4e6ed.worker.js
├── abf5abd2bbdc4ae4e6ed.worker.js.map
├── af7ae505a9eed503f8b8e6982036873e.woff2
├── b06871f281fee6b241d60582ae9369b9.ttf
├── b2444717cd93f718ffad.worker.js
├── b2444717cd93f718ffad.worker.js.map
├── b942d4cc2e310e70c276.worker.js
├── b942d4cc2e310e70c276.worker.js.map
├── cnctoolpath.svg
├── e18bbf611f2a2e43afc071aa2f4e1512.ttf
├── f4769f9bdb7466be65088239c12046d1.eot
├── f917666645dea11914fe.worker.js
├── f917666645dea11914fe.worker.js.map
├── fa2772327f55d8198301fdb8bcfc8158.woff
├── favicon.ico
├── fee66e712a8a08eef5805a46892932ad.woff
├── index.html
├── index.js
└── index.js.map
├── docs
└── laserweb
│ └── 0.4.0
│ ├── Workspace.html
│ ├── actions_dock.js.html
│ ├── actions_panes.js.html
│ ├── classes.list.html
│ ├── com.js.html
│ ├── components_com.js.html
│ ├── components_dock.js.html
│ ├── components_font-awesome.js.html
│ ├── components_laserweb.js.html
│ ├── components_panes.js.html
│ ├── components_sidebar.js.html
│ ├── components_workspace.js.html
│ ├── dock.js.html
│ ├── font-awesome.js.html
│ ├── fonts
│ ├── OpenSans-Bold-webfont.eot
│ ├── OpenSans-Bold-webfont.svg
│ ├── OpenSans-Bold-webfont.woff
│ ├── OpenSans-BoldItalic-webfont.eot
│ ├── OpenSans-BoldItalic-webfont.svg
│ ├── OpenSans-BoldItalic-webfont.woff
│ ├── OpenSans-Italic-webfont.eot
│ ├── OpenSans-Italic-webfont.svg
│ ├── OpenSans-Italic-webfont.woff
│ ├── OpenSans-Light-webfont.eot
│ ├── OpenSans-Light-webfont.svg
│ ├── OpenSans-Light-webfont.woff
│ ├── OpenSans-LightItalic-webfont.eot
│ ├── OpenSans-LightItalic-webfont.svg
│ ├── OpenSans-LightItalic-webfont.woff
│ ├── OpenSans-Regular-webfont.eot
│ ├── OpenSans-Regular-webfont.svg
│ ├── OpenSans-Regular-webfont.woff
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ ├── glyphicons-halflings-regular.woff
│ └── glyphicons-halflings-regular.woff2
│ ├── global.html
│ ├── img
│ ├── glyphicons-halflings-white.png
│ └── glyphicons-halflings.png
│ ├── index.html
│ ├── laserweb.js.html
│ ├── lib_redux-action.js.html
│ ├── module-actions_dock.html
│ ├── module-actions_panes.html
│ ├── module-components_LaserWeb-LaserWeb.html
│ ├── module-components_LaserWeb.html
│ ├── module-components_about-About.html
│ ├── module-components_about.html
│ ├── module-components_cam-Cam.html
│ ├── module-components_cam.html
│ ├── module-components_com-Com.html
│ ├── module-components_com.html
│ ├── module-components_com_network-Network.html
│ ├── module-components_com_network.html
│ ├── module-components_com_serial-Serial.html
│ ├── module-components_com_serial.html
│ ├── module-components_dock-Button.html
│ ├── module-components_dock-Dock.html
│ ├── module-components_dock-Item.html
│ ├── module-components_dock.html
│ ├── module-components_font-awesome-Icon.html
│ ├── module-components_font-awesome.html
│ ├── module-components_gcode-Gcode.html
│ ├── module-components_gcode.html
│ ├── module-components_jog-Jog.html
│ ├── module-components_jog.html
│ ├── module-components_laserweb-LaserWeb.LaserWeb.html
│ ├── module-components_panes-Pane.html
│ ├── module-components_panes-Panes.html
│ ├── module-components_panes.html
│ ├── module-components_quote-Quote.html
│ ├── module-components_quote.html
│ ├── module-components_settings-Settings.html
│ ├── module-components_settings.html
│ ├── module-components_sidebar-Sidebar.html
│ ├── module-components_sidebar.html
│ ├── module-components_sidebar.html#~Sidebar
│ ├── module-components_workspace-Workspace.html
│ ├── module-components_workspace.html
│ ├── module-lib_redux-action.html
│ ├── module-reducers.html
│ ├── module-reducers_dock.html
│ ├── module-reducers_index.html
│ ├── module-reducers_panes.html
│ ├── module.exports.html
│ ├── modules.list.html
│ ├── panes.js.html
│ ├── quicksearch.html
│ ├── reducers_dock.js.html
│ ├── reducers_index.js.html
│ ├── scripts
│ ├── docstrap.lib.js
│ ├── fulltext-search-ui.js
│ ├── fulltext-search.js
│ ├── linenumber.js
│ ├── lunr.min.js
│ ├── prettify
│ │ ├── Apache-License-2.0.txt
│ │ ├── jquery.min.js
│ │ ├── lang-css.js
│ │ └── prettify.js
│ ├── sunlight.js
│ └── toc.js
│ ├── sidebar.js.html
│ ├── styles
│ ├── darkstrap.css
│ ├── jsdoc-default.css
│ ├── prettify-jsdoc.css
│ ├── prettify-tomorrow.css
│ ├── site.cerulean.css
│ ├── site.cosmo.css
│ ├── site.cyborg.css
│ ├── site.darkly.css
│ ├── site.darkstrap.css
│ ├── site.dibs-bootstrap.css
│ ├── site.flatly.css
│ ├── site.journal.css
│ ├── site.lumen.css
│ ├── site.paper.css
│ ├── site.readable.css
│ ├── site.sandstone.css
│ ├── site.simplex.css
│ ├── site.slate.css
│ ├── site.spacelab.css
│ ├── site.superhero.css
│ ├── site.united.css
│ ├── site.yeti.css
│ ├── sunlight.dark.css
│ └── sunlight.default.css
│ └── workspace.js.html
├── git
├── jsdoc.json
├── laserweb@0.4.0
├── logfile.txt
├── package-lock.json
├── package.json
├── src
├── .DS_Store
├── README.md
├── actions
│ ├── camera.js
│ ├── com.js
│ ├── document.js
│ ├── gcode.js
│ ├── laserweb.js
│ ├── macros.js
│ ├── material-database.js
│ ├── object.js
│ ├── operation.js
│ ├── panes.js
│ ├── settings.js
│ ├── splitters.js
│ └── workspace.js
├── cnctoolpath.svg
├── components
│ ├── about.js
│ ├── cam.js
│ ├── capture.js
│ ├── com.js
│ ├── command-history.js
│ ├── dock.js
│ ├── document-cache.js
│ ├── document.js
│ ├── dom3d.js
│ ├── font-awesome.js
│ ├── forms.js
│ ├── get-bounds.js
│ ├── image-filters.js
│ ├── jog.js
│ ├── keyboard.js
│ ├── laserweb.js
│ ├── machine-profiles.js
│ ├── macros.js
│ ├── material-database.js
│ ├── omr.js
│ ├── operation-diagram.js
│ ├── operation.js
│ ├── panes.js
│ ├── quote.js
│ ├── setsize.js
│ ├── settings.js
│ ├── sidebar.js
│ ├── splitter.js
│ ├── subtree.js
│ ├── webcam.js
│ ├── webcam_fx.js
│ └── workspace.js
├── data
│ └── macros.json
├── draw-commands
│ ├── GcodePreview.js
│ ├── LaserPreview.js
│ ├── basic.js
│ ├── image.js
│ ├── imageMesh.js
│ ├── index.js
│ ├── thick-lines.js
│ ├── webcam.js
│ └── webcamfx.js
├── favicon.ico
├── index.html
├── index.js
├── lib
│ ├── Pointable.js
│ ├── action2gcode
│ │ ├── gcode-generator.js
│ │ └── generators
│ │ │ ├── abstract-generator.js
│ │ │ ├── default-generator.js
│ │ │ └── marlin-generator.js
│ ├── cam-gcode-laser-cut.js
│ ├── cam-gcode-lathe.js
│ ├── cam-gcode-mill.js
│ ├── cam-gcode-raster.js
│ ├── cam-gcode-wire.js
│ ├── cam-gcode.js
│ ├── cam.js
│ ├── dxf.js
│ ├── helpers.js
│ ├── js-aruco
│ │ ├── aruco.js
│ │ ├── cv.js
│ │ ├── posit1.js
│ │ ├── posit2.js
│ │ └── svd.js
│ ├── lw.comm-client.js
│ ├── lw.raster2gcode
│ │ ├── canvas-filters.js
│ │ ├── canvas-grid.js
│ │ └── raster-to-gcode.js
│ ├── lw.svg-parser
│ │ ├── parser.js
│ │ ├── tag.js
│ │ └── tagparser.js
│ ├── material-database.js
│ ├── mesh.js
│ ├── omr.js
│ ├── potrace
│ │ └── potrace.js
│ ├── rack-wire.js
│ ├── redux-action.js
│ ├── releases.js
│ ├── storages.js
│ ├── tmpParseGcode.js
│ ├── util.js
│ ├── video-capture.js
│ └── workers
│ │ ├── cam-lasercut.js
│ │ ├── cam-lathe.js
│ │ ├── cam-mill.js
│ │ ├── cam-preflight.js
│ │ ├── cam-raster.js
│ │ └── cam-wire.js
├── reducers
│ ├── camera.js
│ ├── com.js
│ ├── document.js
│ ├── gcode.js
│ ├── index.js
│ ├── machine-profiles.js
│ ├── macros.js
│ ├── material-database.js
│ ├── object.js
│ ├── operation.js
│ ├── panes.js
│ ├── settings.js
│ ├── splitters.js
│ ├── undo.js
│ └── workspace.js
└── styles
│ ├── context-menu.css
│ ├── forms.css
│ ├── index.css
│ ├── material-database.css
│ ├── resizer.css
│ └── webcam.css
├── up_src_to_dist.sh
├── webpack.config.js
├── win.shell.cmd
└── yarn.lock
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/.DS_Store
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["transform-decorators-legacy"]
3 | }
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | Dockerfile*
4 | docker-compose*
5 | .dockerignore
6 | .git
7 | .gitignore
8 | README.md
9 | LICENSE
10 | .vscode
11 | gcodes
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | end_of_line = lf
3 | insert_final_newline = true
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | WEB_PORT=8000
2 | DRO_DECIMALS=2
3 | FIRMWARE_WAIT_TIME=10
4 | GRBL_WAIT_TIME=5
5 | VERBOSE_LEVEL=3
6 | LOG_LEVEL=3
7 | RESET_ON_CONNECT=1
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Laserweb guide to contribution #
2 |
3 | ## Documentation
4 | For more documentation, go to [laserweb.yurl.ch](https://laserweb.yurl.ch)
5 |
6 | ## Community
7 | Please check [The Maker Forums](https://forum.makerforums.info/c/laserweb-cncweb) for discussion on LaserWeb / CNCweb.
8 |
9 | Other than that, this version is mostly stable and not actively developed at the moment.
10 |
11 | ## How to contribute ?
12 |
13 | 1. Fork the original repositiory.
14 | 2. Clone the forked repository.
15 | 3. Create a new branch for your bugfix/feature.
16 | 4. Commit your changes and push it back on Github.
17 | 5. Submit your pull request (Only one feature per pull request).
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Follow this steps to open an issue ###
2 |
3 | - [ ] If refers software, include `Workspace.json`. This is available on *CAM tab top, Workspace -> Save*. Prepare your work, save `workspace.json`, rename as `workspace.json.txt` and attach in this issue. *All resources regarding the issue should be attached (SVG files, images, etc.). An issue opened without resources will be automatically closed upon inspection*
4 |
5 | - [ ] If refers hardware, include enough images, log files, and optionally videos (or link to a Cloud Drive folder) to inspect.
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/.github/PULL_REQUEST_TEMPLATE.md
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | # dist
3 | *.log
4 | .vscode
5 | .zip
6 | machine-profiles.json
7 | gcodes
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/data/lw.machines"]
2 | path = src/data/lw.machines
3 | url = https://github.com/LaserWeb/lw.machines
4 | [submodule "src/data/ew.materials"]
5 | path = src/data/ew.materials
6 | url = https://github.com/Rack-Robotics/ew.materials.git
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '10'
4 | sudo: required
5 | dist: trusty
6 | before_install:
7 | - sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils
8 | - npm install
9 | - npm run installdev
10 | - npm run bundle-dev
11 | addons:
12 | artifacts: true
13 | before_deploy:
14 | - npm -g install asar
15 | - asar pack dist ui.asar
16 | - >
17 | git tag -f "v$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]')"
18 |
19 | deploy:
20 | - provider: pages
21 | skip-cleanup: true
22 | github-token: $GITHUB_TOKEN
23 | keep-history: true
24 | local-dir: dist
25 | on:
26 | branch: dev-es6
27 | tags: true
28 | - provider: releases
29 | api_key:
30 | secure: Xa2aIga7tyQWfBYqGcnXyO/xUVreU0BTz9Bc8GljxsZJfWmWRKPFnnAonzbtmUf+YupGXtYHzbA+hvjm2ifbEkc7sNsa67FywDSh9TeY2ZpAAXgI1gkE4m3PX+OJlE7O0YPGSt7oQl0KcfN+SWR9P42yyok/WlKB+OI7fFgQv35zAk1Q4k3dleJp21pmepHtgK9ZJpv1BgpipQF2nPK2Om6QfS13DX7O8HBfHQpSmJEFpderUyxbYd9ikaIo3fOw1WbZecHu9Xc8tSUsc7ZOVQIxUKI0aKiwkLvJxtZapMMabNVPuYbiS0mAtUEXduDx4c4f8SxpzS1cTCkSOLliekg8oOjohNYKDBzC3rLIJq6eYXjFfuNFjEb/eSbv+sCUmbakSidxnph5LDnkdh3DPXnBtN229v7iLFyTwRqEwbhK/r5RP8yNc9r7ZlRFbGTQTWB2VBaJex2LvWqvD2LUzE9YsSVx19RN8Xda71rMC1FanTVcFjKnjh0xmUXlmxxB3hP3196+BlZqEhTqvypAfVEojH13YHhVYb6K8nfc43raWvN5YHxWTz8fW14jdA1qKNgEOfI8KsQmikKtSYbi6/t2jWYGLg180VaZCyvOMQr/P802MTXq2AjmNziHooRIULx1t+LDii38umXxV9EH4Vet5eJVg/7szu7tqTQ1PBY=
31 | file_glob: true
32 | file: ui.asar
33 | skip_cleanup: true
34 | on:
35 | branch: dev-es6
36 | tags: true
37 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # ---- Base Node ----
3 | FROM node:10-alpine AS base
4 | # set working directory
5 | WORKDIR /usr/src/app
6 |
7 | # copy project file
8 | COPY package*.json ./
9 | EXPOSE 8000
10 | # copy app sources
11 | COPY . .
12 |
13 | #
14 | # ---- Dependencies ----
15 | FROM base AS dependencies
16 | RUN apk add --no-cache libusb-dev eudev-dev make gcc g++ python python3 linux-headers udev git
17 | RUN git config --global url."https://github.com".insteadOf "ssh://git@github.com"
18 | # install node packages
19 | RUN npm set progress=false && npm config set depth 0
20 | RUN npm ci
21 |
22 | #
23 | # ---- Test ----
24 | # run linters, setup and tests
25 | FROM dependencies AS test
26 | #RUN npm run lint && npm run setup && npm run test
27 | RUN npm run test
28 |
29 | #
30 | # ---- Dev ----
31 | FROM dependencies AS dev
32 | RUN npm install && npm install -g nodemon
33 | # copy production node_modules
34 | COPY --from=dependencies /usr/src/app/node_modules node_modules
35 | # define CMD
36 | CMD [ "npm", "run", "start-server" ]
37 |
--------------------------------------------------------------------------------
/Dockerfile.release:
--------------------------------------------------------------------------------
1 | FROM node:10-alpine AS base
2 |
3 | WORKDIR /app
4 |
5 | COPY . .
6 |
7 | RUN apk add --no-cache pkgconfig libusb-dev eudev-dev make gcc g++ python python3 linux-headers udev git
8 | RUN git config --global url."https://github.com".insteadOf "ssh://git@github.com"
9 | RUN npm set progress=false && npm config set depth 0
10 | RUN npm ci
11 | # RUN npm install
12 |
13 | #
14 | # ---- Release ----
15 | FROM node:10-alpine
16 |
17 | ENV ENV="production"
18 | ENV NODE_ENV="production"
19 |
20 | WORKDIR /app
21 | COPY --from=base /app ./
22 |
23 | EXPOSE 8000
24 |
25 | CMD [ "npm", "run", "start-server" ]
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EDMWeb (1.0.x)
2 |
3 | This repository is a "development environment" - and no regular user would have to touch this at all (dont download the repo from here, use the Download links below)
4 |
5 | ## Download
6 | Releases are made available on https://github.com/Rack-Robotics/EDMWeb-Binaries/
7 |
8 | ## Community
9 | Please use the community forum on https://forum.makerforums.info/c/laserweb-cncweb for questions and support.
10 | Please only report confirmed bugs on the git [Issues tab](https://github.com/Rack-Robotics/EDMWeb/issues).
11 |
12 | ## Supported firmwares
13 |
14 | Note: Ever changing. See the Issues tab above for details.
15 |
16 | | Firmware | Supported | Raster Performance | CNC Support |Pull Requests Accepted |
17 | | ------------------------- |------------|:-------------------:|:------------:|:---------------------------------:|
18 | | Grbl > v1.1f (ATmega328) | Yes | Good | Great | Yes - improvements |
19 | | Grbl-Mega (ATmega2560) | Yes | Good | Great | Yes - improvements |
20 | | Grbl-LPC (LPC176x) | Yes | Great | Great | Yes - improvements |
21 | | Grbl_ESP32 (ESP32) | Yes | Great | Great | Yes - improvements |
22 | | Smoothieware | Yes * | Okayish | Okayish | Yes - improvements |
23 | | TinyG | Yes | Unknown | Good | Yes - improvements |
24 | | Marlin | Yes | Unknown | No | Yes - improvements |
25 | | MarlinKimbra | Yes | Unknown | No | Yes - improvements |
26 | | Repetier | Yes | Unknown | No | Yes - improvements |
27 | | RepRapFirmware | Yes | Unknown | Yes | Yes - improvements |
28 |
29 | * If fast raster engraving is important for you, we recommend replacing Smoothieware with grbl-LPC (https://github.com/cprezzi/grbl-LPC) which also runs on the LPC1769 based boards and performs much faster for laser raster applications.
30 |
31 |
32 |
--------------------------------------------------------------------------------
/dist/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/.DS_Store
--------------------------------------------------------------------------------
/dist/448c34a56d699c29117adc64c43affeb.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/448c34a56d699c29117adc64c43affeb.woff2
--------------------------------------------------------------------------------
/dist/674f50d287a8c48dc19ba404d20fe713.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/674f50d287a8c48dc19ba404d20fe713.eot
--------------------------------------------------------------------------------
/dist/af7ae505a9eed503f8b8e6982036873e.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/af7ae505a9eed503f8b8e6982036873e.woff2
--------------------------------------------------------------------------------
/dist/b06871f281fee6b241d60582ae9369b9.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/b06871f281fee6b241d60582ae9369b9.ttf
--------------------------------------------------------------------------------
/dist/e18bbf611f2a2e43afc071aa2f4e1512.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/e18bbf611f2a2e43afc071aa2f4e1512.ttf
--------------------------------------------------------------------------------
/dist/f4769f9bdb7466be65088239c12046d1.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/f4769f9bdb7466be65088239c12046d1.eot
--------------------------------------------------------------------------------
/dist/fa2772327f55d8198301fdb8bcfc8158.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/fa2772327f55d8198301fdb8bcfc8158.woff
--------------------------------------------------------------------------------
/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/favicon.ico
--------------------------------------------------------------------------------
/dist/fee66e712a8a08eef5805a46892932ad.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/dist/fee66e712a8a08eef5805a46892932ad.woff
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | EDMWeb
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/actions_dock.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: actions/dock.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: actions/dock.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Dock actions.
31 | * @module
32 | */
33 |
34 | // Redux action creator factory
35 | import ACF from '../lib/redux-action'
36 |
37 | /**
38 | * Create and return the ADD_BUTTON action.
39 | * @function
40 | * @param {Object} button The button properties. See {@link module:components/dock~Button}.
41 | * @return {module:lib/redux-action~Action}
42 | */
43 | export const addButton = ACF('ADD_BUTTON', 'button')
44 |
45 | /**
46 | * Create and return the REMOVE_BUTTON action.
47 | * @function
48 | * @param {Integer} id The button id.
49 | * @return {module:lib/redux-action~Action}
50 | */
51 | export const removeButton = ACF('REMOVE_BUTTON', 'id')
52 |
53 | /**
54 | * Create and return the SELECT_BUTTON action.
55 | * @function
56 | * @param {Integer} id The button id.
57 | * @return {module:lib/redux-action~Action}
58 | */
59 | export const selectButton = ACF('SELECT_BUTTON', 'id')
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Modules Classes
71 |
72 |
73 |
74 |
75 |
76 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/actions_panes.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: actions/panes.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: actions/panes.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Panes actions.
31 | * @module
32 | */
33 |
34 | // Redux action creator factory
35 | import ACF from '../lib/redux-action'
36 |
37 | /**
38 | * Create and return the ADD_PANE action.
39 | * @function
40 | * @param {Object} pane The pane properties. See {@link module:components/panes~Pane}.
41 | * @return {module:lib/redux-action~Action}
42 | */
43 | export const addPane = ACF('ADD_PANE', 'pane')
44 |
45 | /**
46 | * Create and return the REMOVE_PANE action.
47 | * @function
48 | * @param {Integer} id The pane id.
49 | * @return {module:lib/redux-action~Action}
50 | */
51 | export const removePane = ACF('REMOVE_PANE', 'id')
52 |
53 | /**
54 | * Create and return the SELECT_PANE action.
55 | * @function
56 | * @param {Integer} id The pane id.
57 | * @return {module:lib/redux-action~Action}
58 | */
59 | export const selectPane = ACF('SELECT_PANE', 'id')
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Modules Classes
71 |
72 |
73 |
74 |
75 |
76 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/com.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: com.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: com.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Dock module.
31 | * @module
32 | */
33 |
34 | // React
35 | import React from 'react'
36 |
37 | /**
38 | * Communication component.
39 | *
40 | * @extends module:React~Component
41 | * @param {Object} props Component properties.
42 | */
43 | class Com extends React.Component {
44 | /**
45 | * Render the component.
46 | * @return {String}
47 | */
48 | render() {
49 | return (
50 | <div>
51 | <p>Communication...</p>
52 | </div>
53 | )
54 | }
55 | }
56 |
57 | // Exports
58 | export default Com
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Modules Classes
70 |
71 |
72 |
73 |
74 |
75 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/components_com.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: components/com.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: components/com.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Dock module.
31 | * @module
32 | */
33 |
34 | // React
35 | import React from 'react'
36 |
37 | /**
38 | * Communication component.
39 | *
40 | * @extends module:React~Component
41 | * @param {Object} props Component properties.
42 | */
43 | class Com extends React.Component {
44 | /**
45 | * Render the component.
46 | * @return {String}
47 | */
48 | render() {
49 | return (
50 | <div>
51 | <p>Communication...</p>
52 | </div>
53 | )
54 | }
55 | }
56 |
57 | // Exports
58 | export default Com
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Modules Classes
70 |
71 |
72 |
73 |
74 |
75 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/components_font-awesome.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: components/font-awesome.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: components/font-awesome.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Dock module.
31 | * @module
32 | */
33 |
34 | // React
35 | import React from 'react'
36 |
37 | /**
38 | * Communication component.
39 | *
40 | * @extends module:React~Component
41 | * @param {Object} props Component properties.
42 | */
43 | class Icon extends React.Component {
44 | /**
45 | * @type {Object}
46 | * @member module:components/font-awesome~Icon.prototype#props
47 | * @property {String} name Icon name (without fa- prefix)
48 | * @property {Boolean} fw If true display fixed width icon.
49 | */
50 |
51 | /**
52 | * Return the icon class name from props.
53 | * @return {String}
54 | */
55 | getClassName() {
56 | return 'fa fa-' + this.props.name + (this.props.fw ? ' fa-fw' : '')
57 | }
58 |
59 | /**
60 | * Render the component.
61 | * @return {String}
62 | */
63 | render() {
64 | return (
65 | this.props.name ? <i className={ this.getClassName() }></i> : null
66 | )
67 | }
68 | }
69 |
70 |
71 | // Exports
72 | export default Icon
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Modules Classes
84 |
85 |
86 |
87 |
88 |
89 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/components_laserweb.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: components/laserweb.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: components/laserweb.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * LaserWeb main module (layout).
31 | * - Create the main layout.
32 | * - Set initial state.
33 | * @module
34 | */
35 |
36 | // Styles/Fonts
37 | import 'bootstrap'
38 | import 'bootstrap/dist/css/bootstrap.min.css'
39 | import 'font-awesome/css/font-awesome.min.css'
40 | import '../styles/index.css'
41 |
42 | // React/Redux
43 | import React from 'react'
44 | import { createStore } from 'redux'
45 | import { Provider, connect } from 'react-redux'
46 | import reducers from '../reducers'
47 |
48 | // Main components
49 | import Sidebar from './sidebar'
50 | import Workspace from './workspace'
51 |
52 | // Inner components
53 | import Com from './com'
54 |
55 | // Create redux store
56 | let store = createStore(reducers)
57 |
58 | /**
59 | * LaserWeb main component (layout).
60 | * - Create the main layout.
61 | *
62 | * @extends module:React~Component
63 | * @param {Object} props Component properties.
64 | */
65 | class LaserWeb extends React.Component {
66 | /**
67 | * Render the component.
68 | * @return {String}
69 | */
70 | render() {
71 | return (
72 | <Provider store={store}>
73 | <div className="table">
74 | <Sidebar>
75 | <Com id="com" title="Communication" icon="wifi" active={ true } />
76 | <Com id="com2" title="Communication2" icon="wifi" />
77 | <Com id="com3" title="Communication3" icon="wifi" />
78 | </Sidebar>
79 | <Workspace />
80 | </div>
81 | </Provider>
82 | )
83 | }
84 | }
85 |
86 | // Exports
87 | export default LaserWeb
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Modules Classes
99 |
100 |
101 |
102 |
103 |
104 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/components_workspace.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: components/workspace.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: components/workspace.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Workspace module.
31 | * - Handle workspace modules.
32 | * @module
33 | */
34 |
35 | // React/Redux
36 | import React from 'react'
37 |
38 | /**
39 | * Workspace component.
40 | * - Handle workspace modules.
41 | *
42 | * @extends module:React~Component
43 | * @param {Object} props Component properties.
44 | */
45 | class Workspace extends React.Component {
46 | /**
47 | * Render the component.
48 | * @return {String}
49 | */
50 | render() {
51 | return (
52 | <div id="workspace" className="table-cell">
53 | <p>workspace</p>
54 | </div>
55 | )
56 | }
57 | }
58 |
59 | // Exports
60 | export default Workspace
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Modules Classes
72 |
73 |
74 |
75 |
76 |
77 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/font-awesome.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: font-awesome.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: font-awesome.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Dock module.
31 | * @module
32 | */
33 |
34 | // React
35 | import React from 'react'
36 |
37 | /**
38 | * Communication component.
39 | *
40 | * @extends module:React~Component
41 | * @param {Object} props Component properties.
42 | */
43 | class Icon extends React.Component {
44 | /**
45 | * @type {Object}
46 | * @member module:components/font-awesome~Icon.prototype#props
47 | * @property {String} name Icon name (without fa- prefix)
48 | * @property {Boolean} fw If true display fixed width icon.
49 | */
50 |
51 | /**
52 | * Return the icon class name from props.
53 | * @return {String}
54 | */
55 | getClassName() {
56 | return 'fa fa-' + this.props.name + (this.props.fw ? ' fa-fw' : '')
57 | }
58 |
59 | /**
60 | * Render the component.
61 | * @return {String}
62 | */
63 | render() {
64 | return (
65 | this.props.name ? <i className={ this.getClassName() }></i> : null
66 | )
67 | }
68 | }
69 |
70 |
71 | // Exports
72 | export default Icon
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Modules Classes
84 |
85 |
86 |
87 |
88 |
89 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Bold-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Bold-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Bold-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-BoldItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-BoldItalic-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-BoldItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-BoldItalic-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Italic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Italic-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Italic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Italic-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Light-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Light-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Light-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-LightItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-LightItalic-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-LightItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-LightItalic-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Regular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Regular-webfont.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/OpenSans-Regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/OpenSans-Regular-webfont.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/docs/laserweb/0.4.0/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/laserweb.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: laserweb.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: laserweb.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * LaserWeb main module (layout).
31 | * - Create the main layout.
32 | * - Set initial state.
33 | * @module
34 | */
35 |
36 | // Styles/Fonts
37 | import 'bootstrap'
38 | import 'bootstrap/dist/css/bootstrap.min.css'
39 | import 'font-awesome/css/font-awesome.min.css'
40 | import '../styles/index.css'
41 |
42 | // React/Redux
43 | import React from 'react'
44 | import { createStore } from 'redux'
45 | import { Provider, connect } from 'react-redux'
46 | import reducers from '../reducers'
47 |
48 | // Main components
49 | import Sidebar from './sidebar'
50 | import Workspace from './workspace'
51 |
52 | // Inner components
53 | import Com from './com'
54 |
55 | // Create redux store
56 | let store = createStore(reducers)
57 |
58 | /**
59 | * LaserWeb main component (layout).
60 | * - Create the main layout.
61 | *
62 | * @extends module:React~Component
63 | * @param {Object} props Component properties.
64 | */
65 | class LaserWeb extends React.Component {
66 | /**
67 | * Render the component.
68 | * @return {String}
69 | */
70 | render() {
71 | return (
72 | <Provider store={store}>
73 | <div className="table">
74 | <Sidebar>
75 | <Com id="com" title="Communication" icon="wifi" active={ true } />
76 | <Com id="com2" title="Communication2" icon="wifi" />
77 | <Com id="com3" title="Communication3" icon="wifi" />
78 | </Sidebar>
79 | <Workspace />
80 | </div>
81 | </Provider>
82 | )
83 | }
84 | }
85 |
86 | // Exports
87 | export default LaserWeb
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Modules Classes
99 |
100 |
101 |
102 |
103 |
104 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/module-components_laserweb-LaserWeb.LaserWeb.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Class: LaserWeb
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Class: LaserWeb
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
new LaserWeb(props)
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Create the main layout.
53 | Load all modules.
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
Parameters:
66 |
67 |
68 |
69 |
70 |
71 |
72 | Name
73 |
74 |
75 | Type
76 |
77 |
78 |
79 |
80 |
81 | Description
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | props
91 |
92 |
93 |
94 |
95 |
96 | Object
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | Source:
146 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | Modules Classes
204 |
205 |
206 |
207 |
208 |
209 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 11:59:40 GMT+0200 (Europe de l’Ouest (heure d’été))
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/module-reducers_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Module: reducers/index
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Module: reducers/index
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Source:
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | Modules Classes Global
148 |
149 |
150 |
151 |
152 |
153 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:25:23 GMT+0200 (Europe de l’Ouest (heure d’été))
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/module.exports.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Class: exports
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Class: exports
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Constructor
45 |
46 |
47 |
new exports()
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | Source:
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | Classes
151 |
152 |
153 |
154 |
155 |
156 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 11:07:11 GMT+0200 (Europe de l’Ouest (heure d’été))
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/panes.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: panes.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: panes.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Pane module.
31 | * @module
32 | */
33 |
34 | // React/Redux
35 | import React from 'react'
36 | import { connect } from 'react-redux'
37 |
38 | /**
39 | * Pane component.
40 | *
41 | * @extends module:React~Component
42 | * @param {Object} props Component properties.
43 | */
44 | class Pane extends React.Component {
45 | /**
46 | * @type {Object}
47 | * @member module:components/pane~Pane.prototype#props
48 | * @property {String} key Pane key.
49 | * @property {String} title Pane title.
50 | * @property {String} icon Pane icon name (font-awesome).
51 | * @property {Boolean} active True if active button.
52 | * @property {module:React~Component|module:React~Component[]} children Component children.
53 | */
54 |
55 | /**
56 | * Render the component.
57 | * @return {String}
58 | */
59 | render() {
60 | return (
61 | <div className={ "pane" + (this.props.active ? " active" : "") }>
62 | <h4>{ this.props.title }</h4>
63 | { this.props.children }
64 | </div>
65 | )
66 | }
67 | }
68 |
69 | /**
70 | * Panes component.
71 | * - Handle panes.
72 | *
73 | * @extends module:React~Component
74 | * @param {Object} props Component properties.
75 | */
76 | class Panes extends React.Component {
77 | /**
78 | * @type {Object}
79 | * @member module:components/pane~Panes.prototype#props
80 | * @property {Boolean} visible True if visible.
81 | * @property {module:React~Component|module:React~Component[]} children Component children.
82 | */
83 |
84 | /**
85 | * Render the component.
86 | * @return {String}
87 | */
88 | render() {
89 | return (
90 | <div className={ "panes table-cell " + (this.props.visible ? "" : "hidden") }>
91 | { this.props.children.map(pane => <Pane key={ pane.id } { ...pane } />) }
92 | </div>
93 | )
94 | }
95 | }
96 |
97 | const mapStateToProps = (state) => {
98 | return {
99 | visible: state.panes.visible,
100 | children: state.panes.children
101 | }
102 | }
103 |
104 | const mapDispatchToProps = (dispatch) => {
105 | return {}
106 | }
107 |
108 | // Exports
109 | export { Panes, Pane }
110 | export default connect(mapStateToProps, mapDispatchToProps)(Panes)
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | Modules Classes
122 |
123 |
124 |
125 |
126 |
127 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/reducers_index.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: reducers/index.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: reducers/index.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Combined reducers.
31 | * @module reducers
32 | */
33 |
34 | // Redux reducers combiner
35 | import { combineReducers } from 'redux'
36 |
37 | // Reducers
38 | import dock from './dock'
39 | import panes from './panes'
40 |
41 | // Exports compined reducer
42 | export default combineReducers({ dock, panes })
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | Modules Classes
54 |
55 |
56 |
57 |
58 |
59 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 19:29:58 GMT+0200 (Europe de l’Ouest (heure d’été))
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/scripts/fulltext-search-ui.js:
--------------------------------------------------------------------------------
1 | window.SearcherDisplay = (function($) {
2 | /**
3 | * This class provides support for displaying quick search text results to users.
4 | */
5 | function SearcherDisplay() { }
6 |
7 | SearcherDisplay.prototype.init = function() {
8 | this._displayQuickSearch();
9 | };
10 |
11 | /**
12 | * This method creates the quick text search entry in navigation menu and wires all required events.
13 | */
14 | SearcherDisplay.prototype._displayQuickSearch = function() {
15 | var quickSearch = $(document.createElement("iframe")),
16 | body = $("body"),
17 | self = this;
18 |
19 | quickSearch.attr("src", "quicksearch.html");
20 | quickSearch.css("width", "0px");
21 | quickSearch.css("height", "0px");
22 |
23 | body.append(quickSearch);
24 |
25 | $(window).on("message", function(msg) {
26 | var msgData = msg.originalEvent.data;
27 |
28 | if (msgData.msgid != "docstrap.quicksearch.done") {
29 | return;
30 | }
31 |
32 | var results = msgData.results || [];
33 |
34 | self._displaySearchResults(results);
35 | });
36 |
37 | function startSearch() {
38 | var searchTerms = $('#search-input').prop("value");
39 | if (searchTerms) {
40 | quickSearch[0].contentWindow.postMessage({
41 | "searchTerms": searchTerms,
42 | "msgid": "docstrap.quicksearch.start"
43 | }, "*");
44 | }
45 | }
46 |
47 | $('#search-input').on('keyup', function(evt) {
48 | if (evt.keyCode != 13) {
49 | return;
50 | }
51 | startSearch();
52 | return false;
53 | });
54 | $('#search-submit').on('click', function() {
55 | startSearch();
56 | return false;
57 | });
58 | };
59 |
60 | /**
61 | * This method displays the quick text search results in a modal dialog.
62 | */
63 | SearcherDisplay.prototype._displaySearchResults = function(results) {
64 | var resultsHolder = $($("#searchResults").find(".modal-body")),
65 | fragment = document.createDocumentFragment(),
66 | resultsList = document.createElement("ul");
67 |
68 | resultsHolder.empty();
69 |
70 | for (var idx = 0; idx < results.length; idx++) {
71 | var result = results[idx],
72 | item = document.createElement("li"),
73 | link = document.createElement("a");
74 |
75 | link.href = result.id;
76 | link.innerHTML = result.title;
77 |
78 | item.appendChild(link)
79 | resultsList.appendChild(item);
80 | }
81 |
82 | fragment.appendChild(resultsList);
83 | resultsHolder.append(fragment);
84 |
85 | $("#searchResults").modal({"show": true});
86 | };
87 |
88 | return new SearcherDisplay();
89 | })($);
90 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/scripts/fulltext-search.js:
--------------------------------------------------------------------------------
1 | window.Searcher = (function() {
2 | function Searcher() {
3 | this._index = lunr(function () {
4 | this.field('title', {boost: 10})
5 | this.field('body')
6 | this.ref('id')
7 | }) ;
8 |
9 | this._indexContent = undefined;
10 | }
11 |
12 | Searcher.prototype.init = function() {
13 | var self = this;
14 |
15 | $("script[type='text/x-docstrap-searchdb']").each(function(idx, item) {
16 | self._indexContent = JSON.parse(item.innerHTML);
17 |
18 | for (var entryId in self._indexContent) {
19 | self._index.add(self._indexContent[entryId]);
20 | }
21 | });
22 | };
23 |
24 | Searcher.prototype.search = function(searchTerm) {
25 | var results = [],
26 | searchResults = this._index.search(searchTerm);
27 |
28 | for (var idx = 0; idx < searchResults.length; idx++) {
29 | results.push(this._indexContent[searchResults[idx].ref])
30 | }
31 |
32 | return results;
33 | };
34 |
35 | return new Searcher();
36 | })();
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/scripts/linenumber.js:
--------------------------------------------------------------------------------
1 | /*global document */
2 | (function() {
3 | var source = document.getElementsByClassName('prettyprint source linenums');
4 | var i = 0;
5 | var lineNumber = 0;
6 | var lineId;
7 | var lines;
8 | var totalLines;
9 | var anchorHash;
10 |
11 | if (source && source[0]) {
12 | anchorHash = document.location.hash.substring(1);
13 | lines = source[0].getElementsByTagName('li');
14 | totalLines = lines.length;
15 |
16 | for (; i < totalLines; i++) {
17 | lineNumber++;
18 | lineId = 'line' + lineNumber;
19 | lines[i].id = lineId;
20 | if (lineId === anchorHash) {
21 | lines[i].className += ' selected';
22 | }
23 | }
24 | }
25 | })();
26 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([
2 | ["pln", /^[\t\n\f\r ]+/, null, " \t\r\n"]
3 | ], [
4 | ["str", /^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/, null],
5 | ["str", /^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/, null],
6 | ["lang-css-str", /^url\(([^"')]*)\)/i],
7 | ["kwd", /^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i, null],
8 | ["lang-css-kw", /^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],
9 | ["com", /^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],
10 | ["com", /^(?:<\!--|--\>)/],
11 | ["lit", /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],
12 | ["lit", /^#[\da-f]{3,6}/i],
13 | ["pln", /^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],
14 | ["pun", /^[^\s\w"']+/]
15 | ]), ["css"]);
16 | PR.registerLangHandler(PR.createSimpleLexer([], [
17 | ["kwd", /^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]
18 | ]), ["css-kw"]);
19 | PR.registerLangHandler(PR.createSimpleLexer([], [
20 | ["str", /^[^"')]+/]
21 | ]), ["css-str"]);
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/sidebar.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: sidebar.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: sidebar.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Sidebar module.
31 | * @module
32 | */
33 |
34 | // React/Redux
35 | import React from 'react'
36 | import { connect } from 'react-redux'
37 |
38 | // Main components
39 | import Dock from './dock'
40 | import Panes from './panes'
41 |
42 | // Actions
43 | import * as dockActions from '../actions/dock'
44 | import * as panesActions from '../actions/panes'
45 |
46 | /**
47 | * Sidebar component.
48 | * - Handle sidebar modules.
49 | *
50 | * @extends module:React~Component
51 | * @param {Object} props Component properties.
52 | */
53 | class Sidebar extends React.Component {
54 | /**
55 | * @type {Object}
56 | * @member module:components/sidebar~Sidebar.prototype#props
57 | * @property {module:React~Component|module:React~Component[]} children Component children.
58 | * @property {module:components/sidebar~addModule} addModule Add module dock/pane to the sidebar.
59 | */
60 |
61 | constructor(props) {
62 | // Super constructor
63 | super(props)
64 |
65 | // Add each children dock/pane to the sidebar
66 | React.Children.forEach(this.props.children, (child) => {
67 | this.props.addModule(child.props)
68 | })
69 | }
70 |
71 | /**
72 | * Render the component.
73 | * @return {String}
74 | */
75 | render() {
76 | return (
77 | <div id="sidebar" className="table-cell">
78 | <div className="table">
79 | <Dock />
80 | <Panes />
81 | </div>
82 | </div>
83 | )
84 | }
85 | }
86 |
87 | const mapStateToProps = (state) => {
88 | return {}
89 | }
90 |
91 | const mapDispatchToProps = (dispatch) => {
92 | return {
93 | /**
94 | * Add module dock/pane to the sidebar.
95 | * @typedef {Function} module:components/sidebar~addModule
96 | * @param {Object} props Component properties.
97 | */
98 | addModule: (props) => {
99 | dispatch(dockActions.addButton(props))
100 | dispatch(panesActions.addPane(props))
101 | }
102 | }
103 | }
104 |
105 | export default connect(mapStateToProps, mapDispatchToProps)(Sidebar)
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | Modules Classes
117 |
118 |
119 |
120 |
121 |
122 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/styles/prettify-jsdoc.css:
--------------------------------------------------------------------------------
1 | /* JSDoc prettify.js theme */
2 |
3 | /* plain text */
4 | .pln {
5 | color: #000000;
6 | font-weight: normal;
7 | font-style: normal;
8 | }
9 |
10 | /* string content */
11 | .str {
12 | color: #006400;
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
17 | /* a keyword */
18 | .kwd {
19 | color: #000000;
20 | font-weight: bold;
21 | font-style: normal;
22 | }
23 |
24 | /* a comment */
25 | .com {
26 | font-weight: normal;
27 | font-style: italic;
28 | }
29 |
30 | /* a type name */
31 | .typ {
32 | color: #000000;
33 | font-weight: normal;
34 | font-style: normal;
35 | }
36 |
37 | /* a literal value */
38 | .lit {
39 | color: #006400;
40 | font-weight: normal;
41 | font-style: normal;
42 | }
43 |
44 | /* punctuation */
45 | .pun {
46 | color: #000000;
47 | font-weight: bold;
48 | font-style: normal;
49 | }
50 |
51 | /* lisp open bracket */
52 | .opn {
53 | color: #000000;
54 | font-weight: bold;
55 | font-style: normal;
56 | }
57 |
58 | /* lisp close bracket */
59 | .clo {
60 | color: #000000;
61 | font-weight: bold;
62 | font-style: normal;
63 | }
64 |
65 | /* a markup tag name */
66 | .tag {
67 | color: #006400;
68 | font-weight: normal;
69 | font-style: normal;
70 | }
71 |
72 | /* a markup attribute name */
73 | .atn {
74 | color: #006400;
75 | font-weight: normal;
76 | font-style: normal;
77 | }
78 |
79 | /* a markup attribute value */
80 | .atv {
81 | color: #006400;
82 | font-weight: normal;
83 | font-style: normal;
84 | }
85 |
86 | /* a declaration */
87 | .dec {
88 | color: #000000;
89 | font-weight: bold;
90 | font-style: normal;
91 | }
92 |
93 | /* a variable name */
94 | .var {
95 | color: #000000;
96 | font-weight: normal;
97 | font-style: normal;
98 | }
99 |
100 | /* a function name */
101 | .fun {
102 | color: #000000;
103 | font-weight: bold;
104 | font-style: normal;
105 | }
106 |
107 | /* Specify class=linenums on a pre to get line numbering */
108 | ol.linenums {
109 | margin-top: 0;
110 | margin-bottom: 0;
111 | }
112 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/styles/prettify-tomorrow.css:
--------------------------------------------------------------------------------
1 | /* Tomorrow Theme */
2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
3 | /* Pretty printing styles. Used with prettify.js. */
4 | /* SPAN elements with the classes below are added by prettyprint. */
5 | /* plain text */
6 | .pln {
7 | color: #4d4d4c; }
8 |
9 | @media screen {
10 | /* string content */
11 | .str {
12 | color: #718c00; }
13 |
14 | /* a keyword */
15 | .kwd {
16 | color: #8959a8; }
17 |
18 | /* a comment */
19 | .com {
20 | color: #8e908c; }
21 |
22 | /* a type name */
23 | .typ {
24 | color: #4271ae; }
25 |
26 | /* a literal value */
27 | .lit {
28 | color: #f5871f; }
29 |
30 | /* punctuation */
31 | .pun {
32 | color: #4d4d4c; }
33 |
34 | /* lisp open bracket */
35 | .opn {
36 | color: #4d4d4c; }
37 |
38 | /* lisp close bracket */
39 | .clo {
40 | color: #4d4d4c; }
41 |
42 | /* a markup tag name */
43 | .tag {
44 | color: #c82829; }
45 |
46 | /* a markup attribute name */
47 | .atn {
48 | color: #f5871f; }
49 |
50 | /* a markup attribute value */
51 | .atv {
52 | color: #3e999f; }
53 |
54 | /* a declaration */
55 | .dec {
56 | color: #f5871f; }
57 |
58 | /* a variable name */
59 | .var {
60 | color: #c82829; }
61 |
62 | /* a function name */
63 | .fun {
64 | color: #4271ae; } }
65 | /* Use higher contrast and text-weight for printable form. */
66 | @media print, projection {
67 | .str {
68 | color: #060; }
69 |
70 | .kwd {
71 | color: #006;
72 | font-weight: bold; }
73 |
74 | .com {
75 | color: #600;
76 | font-style: italic; }
77 |
78 | .typ {
79 | color: #404;
80 | font-weight: bold; }
81 |
82 | .lit {
83 | color: #044; }
84 |
85 | .pun, .opn, .clo {
86 | color: #440; }
87 |
88 | .tag {
89 | color: #006;
90 | font-weight: bold; }
91 |
92 | .atn {
93 | color: #404; }
94 |
95 | .atv {
96 | color: #060; } }
97 | /* Style */
98 | /*
99 | pre.prettyprint {
100 | background: white;
101 | font-family: Menlo, Monaco, Consolas, monospace;
102 | font-size: 12px;
103 | line-height: 1.5;
104 | border: 1px solid #ccc;
105 | padding: 10px; }
106 | */
107 |
108 | /* Specify class=linenums on a pre to get line numbering */
109 | ol.linenums {
110 | margin-top: 0;
111 | margin-bottom: 0; }
112 |
113 | /* IE indents via margin-left */
114 | li.L0,
115 | li.L1,
116 | li.L2,
117 | li.L3,
118 | li.L4,
119 | li.L5,
120 | li.L6,
121 | li.L7,
122 | li.L8,
123 | li.L9 {
124 | /* */ }
125 |
126 | /* Alternate shading for lines */
127 | li.L1,
128 | li.L3,
129 | li.L5,
130 | li.L7,
131 | li.L9 {
132 | /* */ }
133 |
--------------------------------------------------------------------------------
/docs/laserweb/0.4.0/workspace.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: workspace.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: workspace.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Workspace module.
31 | * - Handle workspace modules.
32 | * @module
33 | */
34 |
35 | // React/Redux
36 | import React from 'react'
37 |
38 | /**
39 | * Workspace component.
40 | * - Handle workspace modules.
41 | *
42 | * @extends module:React~Component
43 | * @param {Object} props Component properties.
44 | */
45 | class Workspace extends React.Component {
46 | /**
47 | * Render the component.
48 | * @return {String}
49 | */
50 | render() {
51 | return (
52 | <div id="workspace" className="table-cell">
53 | <p>workspace</p>
54 | </div>
55 | )
56 | }
57 | }
58 |
59 | // Exports
60 | export default Workspace
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Modules Classes
72 |
73 |
74 |
75 |
76 |
77 | Documentation generated by JSDoc 3.4.1 on Wed Sep 28 2016 18:20:12 GMT+0200 (Europe de l’Ouest (heure d’été))
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/git:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/git
--------------------------------------------------------------------------------
/jsdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags": {
3 | "allowUnknownTags": true
4 | },
5 | "source": {
6 | "include": ["./src/"],
7 | "includePattern": ".+\\.js(doc|x)?$",
8 | "excludePattern": "(^|\\/|\\\\)_"
9 | },
10 | "opts": {
11 | "template": "./node_modules/ink-docstrap/template",
12 | "package": "./package.json",
13 | "destination": "./docs/",
14 | "encoding": "utf8",
15 | "recurse": true,
16 | "private": true
17 | },
18 | "plugins": ["plugins/markdown"],
19 | "templates": {
20 | "cleverLinks": false,
21 | "monospaceLinks": true,
22 | "default": {
23 | "outputSourceFiles": true,
24 | "useLongnameInNav": true
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/laserweb@0.4.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/laserweb@0.4.0
--------------------------------------------------------------------------------
/logfile.txt:
--------------------------------------------------------------------------------
1 | 2023-06-20 03:02:43
2 | 2023-06-20 03:02:43 ***************************************************************
3 | 2023-06-20 03:02:43 ---- LaserWeb Comm Server 4.1.000 ----
4 | 2023-06-20 03:02:43 ***************************************************************
5 | 2023-06-20 03:02:43 Use http://192.168.4.56:8000 to connect to this server.
6 | 2023-06-20 03:02:43
7 | 2023-06-20 03:02:43 * Updates:
8 | 2023-06-20 03:02:43 Remember to check the commit log on
9 | 2023-06-20 03:02:43 https://github.com/LaserWeb/lw.comm-server/commits/master
10 | 2023-06-20 03:02:43 regularly, to know about updates and fixes, and then when ready
11 | 2023-06-20 03:02:43 update accordingly by running git pull
12 | 2023-06-20 03:02:43
13 | 2023-06-20 03:02:43 * Support:
14 | 2023-06-20 03:02:43 If you need help / support, come over to
15 | 2023-06-20 03:02:43 https://forum.makerforums.info/c/laserweb-cncweb/78
16 | 2023-06-20 03:02:43 ***************************************************************
17 | 2023-06-20 03:02:43
18 | 2023-06-20 03:02:43 Server binding to all local IP addresses on port: 8000
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "edmweb",
3 | "version": "1.0.0",
4 | "description": "EDMWeb",
5 | "main": "./src/index.js",
6 | "scripts": {
7 | "start-server": "node node_modules/ew.comm-server/server.js",
8 | "start-app": "webpack-dev-server --progress --colors --open",
9 | "start-prod": "webpack-dev-server -p --progress --colors --open",
10 | "start": "npm-run-all -p -r start-app start-server",
11 | "bundle-dev": "webpack --progress --colors",
12 | "bundle-prod": "webpack -p --progress --colors",
13 | "build-docs": "jsdoc -c ./jsdoc.json",
14 | "installdev": "git submodule init && git submodule update --remote && npm install && npm update ew.comm-server",
15 | "golive": "git checkout gh-pages && git pull && git merge dev-es6 && npm run bundle-dev && git add dist && git commit -m regen && git push && git checkout dev-es6"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/Rack-Robotics/EDMWeb.git"
20 | },
21 | "keywords": [
22 | "laser",
23 | "cnc",
24 | "cam",
25 | "..."
26 | ],
27 | "author": "Peter van der Walt ",
28 | "contributors": [
29 | "Peter van der Walt ",
30 | "Sébastien Mischler ",
31 | "João Matos ",
32 | "Todd Fleming ",
33 | "Jorge Robles ",
34 | "Claudio Prezzi "
35 | ],
36 | "license": "AGPL-3.0",
37 | "bugs": {
38 | "url": "https://github.com/Rack-Robotics/EDMWeb/issues"
39 | },
40 | "homepage": "https://laserweb.yurl.ch",
41 | "devDependencies": {
42 | "ajv": "^5.2.1",
43 | "array-move": "^1.0.0",
44 | "aruco-marker": "^2.0.0",
45 | "babel-core": "^6.26.0",
46 | "babel-loader": "^7.1.2",
47 | "babel-plugin-transform-decorators": "^6.24.1",
48 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
49 | "babel-plugin-transform-es2015-destructuring": "^6.23.0",
50 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
51 | "babel-plugin-transform-es2015-parameters": "^6.24.1",
52 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
53 | "babel-polyfill": "^6.26.0",
54 | "babel-preset-react": "^6.24.1",
55 | "bootstrap": "^3.4.1",
56 | "chunk": "0.0.2",
57 | "clipper-lib": "^6.2.1",
58 | "color-convert": "^1.9.0",
59 | "css-loader": "^0.28.5",
60 | "ew.comm-server": "git+https://github.com/Rack-Robotics/ew.comm-server.git",
61 | "file-loader": "^0.11.2",
62 | "flat": "^2.0.1",
63 | "floyd-steinberg": "^1.0.6",
64 | "font-awesome": "^4.6.3",
65 | "gamepad.js": "git+https://github.com/neogeek/gamepad.js.git#d3f8f96e79",
66 | "gl-matrix": "^2.3.2",
67 | "hhmmss": "^1.0.0",
68 | "imports-loader": "^0.7.1",
69 | "ink-docstrap": "^1.3.2",
70 | "jquery": "^3.7.0",
71 | "json-stringify-pretty-compact": "^1.0.2",
72 | "keyboardjs": "^2.5.1",
73 | "lw.canvas-filters": "git+https://github.com/LaserWeb/lw.canvas-filters.git",
74 | "lw.canvas-grid": "git+https://github.com/LaserWeb/lw.canvas-grid.git",
75 | "lw.raster-to-gcode": "git+https://github.com/LaserWeb/lw.raster-to-gcode.git",
76 | "lw.svg-curves": "^0.1.0",
77 | "lw.svg-path": "^0.1.0",
78 | "marked": "^0.3.9",
79 | "npm-run-all": "^4.1.5",
80 | "object-to-string": "^1.0.0",
81 | "poly2tri": "^1.3.5",
82 | "prefix-keys": "^1.0.0",
83 | "queue": "^4.5.1",
84 | "react": "^15.6.1",
85 | "react-bootstrap": "^0.31.2",
86 | "react-contextmenu": "^2.11.0",
87 | "react-dom": "^15.6.1",
88 | "react-draggable": "^2.2.6",
89 | "react-hot-loader": "^3.0.0-beta.7",
90 | "react-redux": "^5.1.1",
91 | "react-rnd": "^4.2.2",
92 | "react-select": "^1.0.0-rc.5",
93 | "react-toggle": "^4.1.1",
94 | "redux": "^3.7.2",
95 | "redux-localstorage": "^1.0.0-rc5",
96 | "redux-localstorage-filter": "^0.1.1",
97 | "redux-logger": "^3.0.6",
98 | "script-loader": "^0.7.0",
99 | "sillyname": "^0.1.0",
100 | "slug": "^0.9.4",
101 | "snapsvg": "^0.5.1",
102 | "socket.io-client": "^4.6.2",
103 | "style-loader": "^0.18.2",
104 | "url-loader": "^0.5.9",
105 | "utf-8-validate": "^6.0.3",
106 | "uuid": "^3.3.3",
107 | "validatorjs": "^3.17.1",
108 | "vex-js": "^3.1.0",
109 | "web-cam-cpp": "git+https://github.com/LaserWeb/web-cam-cpp.git",
110 | "webpack": "^2.2.1",
111 | "webpack-dev-server": "2.11.1",
112 | "webrtc-adapter": "^3.1.5",
113 | "worker-loader": "^0.8.1",
114 | "xregexp": "^4.2.4"
115 | },
116 | "dependencies": {
117 | "bootstrap-range-input": "^1.0.0",
118 | "bufferutil": "^4.0.7",
119 | "dxf-parser": "^0.4.8",
120 | "hoek": "^5.0.3",
121 | "immutability-helper": "^2.9.1",
122 | "object.omit": "^3.0.0",
123 | "unicode": "^9.0.0",
124 | "vectorize-text": "^3.2.1"
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/src/.DS_Store
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | # LaserWeb (0.4.0-alpha)
2 | Work In Progress...
3 |
--------------------------------------------------------------------------------
/src/actions/camera.js:
--------------------------------------------------------------------------------
1 | import { setAttrs } from '../actions/object'
2 |
3 | export const setCameraAttrs = setAttrs('camera');
4 |
5 | export function zoomArea(x1, y1, x2, y2) {
6 | return { type: 'CAMERA_ZOOM_AREA', x1, y1, x2, y2 };
7 | }
8 |
--------------------------------------------------------------------------------
/src/actions/com.js:
--------------------------------------------------------------------------------
1 | import { setAttrs } from '../actions/object'
2 |
3 | /*SETTINGS*/
4 | export const setComAttrs = setAttrs('com');
5 |
--------------------------------------------------------------------------------
/src/actions/document.js:
--------------------------------------------------------------------------------
1 | import { setAttrs, add, addChild, remove } from '../actions/object'
2 |
3 | export const setDocumentAttrs = setAttrs('document');
4 | export const addDocument = add('document');
5 | export const addDocumentChild = addChild('document');
6 | export const removeDocument = remove('document');
7 |
8 | export function selectDocument(id) {
9 | return { type: 'DOCUMENT_SELECT', payload: { id } };
10 | };
11 |
12 | export function toggleSelectDocument(id) {
13 | return { type: 'DOCUMENT_TOGGLE_SELECT', payload: { id } };
14 | };
15 |
16 | export function toggleVisibleDocument(id) {
17 | return { type: 'DOCUMENT_TOGGLE_VISIBLE', payload: { id } };
18 | };
19 |
20 | export function transform2dSelectedDocuments(transform2d) {
21 | return { type: 'DOCUMENT_TRANSFORM2D_SELECTED', payload: transform2d };
22 | }
23 |
24 | export function loadDocument(file, content, modifiers = {}, context = undefined) {
25 | return { type: 'DOCUMENT_LOAD', payload: { file, content, context, modifiers } };
26 | }
27 |
28 | export function removeDocumentSelected() {
29 | return { type: 'DOCUMENT_REMOVE_SELECTED' };
30 | }
31 |
32 | export function cloneDocumentSelected() {
33 | return { type: 'DOCUMENT_CLONE_SELECTED' };
34 | }
35 |
36 | export function selectDocuments(meta){
37 | return { type: 'DOCUMENT_SELECT_META', payload:{meta} };
38 | }
39 |
40 | export function colorDocumentSelected(color){
41 | return { type: 'DOCUMENT_COLOR_SELECTED', payload:{color} };
42 | }
--------------------------------------------------------------------------------
/src/actions/gcode.js:
--------------------------------------------------------------------------------
1 | export function setGcode(gcode) {
2 | return { type: 'GCODE_SET', payload: gcode };
3 | }
4 |
5 | export function generatingGcode(enable, percent=0) {
6 | return { type: 'GCODE_GENERATION', payload: {enable, percent: percent!==undefined ? percent : 0}};
7 | }
--------------------------------------------------------------------------------
/src/actions/laserweb.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const keyboardUndoAction = (event) => ({ type: 'UNDO', payload: {} });
4 |
5 | export const resetWorkspace = () => ({ type: 'WORKSPACE_RESET', payload: {} });
--------------------------------------------------------------------------------
/src/actions/macros.js:
--------------------------------------------------------------------------------
1 | import { setAttrs, add, remove, reset } from '../actions/object'
2 |
3 |
4 | export const setMacro = setAttrs('macros');
5 | export const addMacro = add('macros');
6 | export const removeMacro = remove('macros');
7 |
8 | export function fireMacroById(keybinding, macros) {
9 | let macro = Object.values(macros).find((i) => i.keybinding === keybinding);
10 | if (macro) {
11 | let { label, gcode } = macro;
12 | return { type: 'MACRO_FIRE', payload: { keybinding, label, gcode } }
13 | }
14 | return null;
15 | }
--------------------------------------------------------------------------------
/src/actions/material-database.js:
--------------------------------------------------------------------------------
1 | import { setAttrs } from '../actions/object'
2 |
3 | /*MATERIALDB_GROUP*/
4 | export const addGroup = () => ({ type: "MATERIALDB_GROUP_ADD" });
5 | export const deleteGroup = (groupId) => ({ type: "MATERIALDB_GROUP_DELETE", payload: groupId });
6 | export const setGroupAttrs = (groupId, attrs) => ({ type: "MATERIALDB_GROUP_SET_ATTRS", payload: { groupId, attrs } });
7 | export const toggleGroupView = (groupId) => ({ type: "MATERIALDB_GROUP_TOGGLE_VIEW", payload: groupId });
8 | export const toggleGroupEdit = (groupId) => ({ type: "MATERIALDB_GROUP_TOGGLE_EDIT", payload: groupId });
9 |
10 | /*MATERIALDB_PRESET (operations)*/
11 | export const addPreset = (groupId, attrs = {}) => ({ type: "MATERIALDB_PRESET_ADD", payload: { groupId, attrs } })
12 | export const deletePreset = (presetId) => ({ type: "MATERIALDB_PRESET_DELETE", payload: presetId });
13 | export const setPresetAttrs = (presetId, attrs) => ({ type: "MATERIALDB_PRESET_SET_ATTRS", payload: { presetId, attrs } });
14 | export const togglePresetEdit = (presetId) => ({ type: "MATERIALDB_PRESET_TOGGLE_EDIT", payload: presetId });
15 |
16 | /*MATERIALDB PICKER*/
17 | export const applyPreset = (presetId) => ({ type: "MATERIALDB_PRESET_APPLY", payload: presetId });
18 | export const newPreset = (preset, grouping, name) => ({ type: "MATERIALDB_PRESET_NEW", payload: { preset, grouping, name } })
19 |
20 | /*MATERIALDB*/
21 | export const uploadMaterialDatabase = (file, content) => ({ type: "MATERIALDB_UPLOAD", payload: { file, database: JSON.parse(content) } });
22 | export const importMaterialDatabase = (file, content) => ({ type: "MATERIALDB_IMPORT", payload: { file, database: content } });
23 | export const downloadMaterialDatabase = (database) => ({ type: "MATERIALDB_DOWNLOAD", payload: { database } });
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/actions/object.js:
--------------------------------------------------------------------------------
1 | // TODO: need a better name than 'object'. Some name that's pretty general.
2 |
3 | import uuidv4 from 'uuid/v4';
4 |
5 | // Set attributes on an object.
6 | //
7 | // objectType: e.g. 'document', 'operation'. Case ignored.
8 | // attrs: e.g. {type: 'pocket', depth: 7}
9 | // id
10 | export function setAttrs(objectType) {
11 | let type = objectType.toUpperCase() + '_SET_ATTRS';
12 | return (attrs, id) => ({ type, payload: { id, attrs } });
13 | };
14 |
15 | // Add an object to a container.
16 | //
17 | // objectType: e.g. 'document', 'operation'. Case ignored.
18 | // defaults: altered state callback for the first population
19 | // attrs: optional. e.g. {type: 'pocket', depth: 7}
20 | export function add(objectType, defaults=function(){return {}}) {
21 | let type = objectType.toUpperCase() + '_ADD';
22 | return (attrs) => ({ type, payload: { attrs: { ...defaults(), ...attrs, id: attrs.id || uuidv4() } } });
23 | };
24 |
25 | // Add a child to a parent. attrs is optional.
26 | //
27 | // objectType: e.g. 'document', 'operation'. Case ignored.
28 | // parentId
29 | // attrs: optional. e.g. {type: 'pocket', depth: 7}
30 | export function addChild(objectType) {
31 | let type = objectType.toUpperCase() + '_ADD_CHILD';
32 | return (parentId, attrs) =>
33 | ({ type, payload: { parentId, attrs: { ...attrs, id: attrs.id || uuidv4() } } });;
34 | };
35 |
36 | // Remove an object from a container.
37 | //
38 | // objectType: e.g. 'document', 'operation'. Case ignored.
39 | // id
40 | export function remove(objectType) {
41 | let type = objectType.toUpperCase() + '_REMOVE';
42 | return (id) => ({ type, payload: id });
43 | };
44 |
--------------------------------------------------------------------------------
/src/actions/operation.js:
--------------------------------------------------------------------------------
1 | import { setAttrs, add, remove } from '../actions/object'
2 | import { OPERATION_DEFAULTS } from '../reducers/operation'
3 | import uuidv4 from 'uuid/v4';
4 |
5 | export const setOperationAttrs = setAttrs('operation');
6 | export const addOperation = add('operation',OPERATION_DEFAULTS);
7 | export const removeOperation = remove('operation');
8 |
9 | export function operationAddDocuments(id, isTab, documents) {
10 | return { type: 'OPERATION_ADD_DOCUMENTS', payload: { id, isTab, documents } };
11 | }
12 |
13 | export function operationRemoveDocument(id, isTab, document) {
14 | return { type: 'OPERATION_REMOVE_DOCUMENT', payload: { id, isTab, document } };
15 | }
16 |
17 | export function setCurrentOperation(id) {
18 | return { type: 'OPERATION_SET_CURRENT', payload: id };
19 | }
20 |
21 | export function moveOperation(id, step) {
22 | return { type: 'OPERATION_MOVE_CURRENT', payload: { id, step } };
23 | }
24 |
25 | export function clearOperations()
26 | {
27 | return { type: 'OPERATION_CLEAR_ALL' };
28 | }
29 |
30 | export function spreadOperationField(id, field)
31 | {
32 | return { type: 'OPERATION_SPREAD_FIELD', payload: {id, field} }
33 | }
34 |
35 | export function operationLatheTurnAdd(id, attrs) {
36 | return { type: 'OPERATION_LATHE_TURN_ADD', payload: { id, attrs: { ...attrs, id: uuidv4() } } };
37 | }
38 |
39 | export const operationLatheTurnSetAttrs = setAttrs('operation_lathe_turn');
40 | export const operationLatheTurnRemove = remove('operation_lathe_turn');
41 |
--------------------------------------------------------------------------------
/src/actions/panes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Panes actions.
3 | * @module
4 | */
5 |
6 | // Redux action creator factory
7 | import ACF from '../lib/redux-action'
8 |
9 | /**
10 | * Create and return the SELECT_PANE action.
11 | * @function
12 | * @param {Integer} id The pane id.
13 | * @return {module:lib/redux-action~Action}
14 | */
15 | export const selectPane = ACF('SELECT_PANE', 'id')
16 |
--------------------------------------------------------------------------------
/src/actions/settings.js:
--------------------------------------------------------------------------------
1 | import { setAttrs } from '../actions/object'
2 |
3 | /*SETTINGS*/
4 | export const setSettingsAttrs = setAttrs('settings');
5 | export const uploadSettings = (file, content) => ({ /*SETTINGS_UPLOAD*/ type:"SETTINGS_SET_ATTRS", payload: {attrs:JSON.parse(content)}});
6 | export const downloadSettings = (settings) => ({ type:"SETTINGS_DOWNLOAD", payload: settings});
7 |
8 | /*MACHINEPROFILES*/
9 | export const addMachineProfile = (id, machine) => ({type: 'MACHINEPROFILES_ADD', payload: {id, machine}})
10 | export const delMachineProfileId = (id) => ({type: 'MACHINEPROFILES_REMOVE', payload: {id}})
11 | export const uploadMachineProfiles = (file, content) => ({ type:"MACHINEPROFILES_UPLOAD", payload: {file, machines:JSON.parse(content)}});
12 | export const downloadMachineProfiles = (machines) => ({ type:"MACHINEPROFILES_DOWNLOAD", payload: {machines}});
13 |
14 | /*SNAPSHOT*/
15 | export const uploadSnapshot = (file, content, keys) => ({ type:"SNAPSHOT_UPLOAD", payload: {file, keys, snapshot:JSON.parse(content)}});
16 | export const downloadSnapshot = (snapshot) => ({ type:"SNAPSHOT_DOWNLOAD", payload: {snapshot}});
17 | export const storeSnapshot = (key, content) => ({ type:"SNAPSHOT_STORE", payload: {key, content}});
--------------------------------------------------------------------------------
/src/actions/splitters.js:
--------------------------------------------------------------------------------
1 | export function splitterSetSize(id, size) {
2 | return { type: 'SPLITTER_SET_SIZE', payload: { id, size } };
3 | };
4 |
--------------------------------------------------------------------------------
/src/actions/workspace.js:
--------------------------------------------------------------------------------
1 | import { setAttrs } from '../actions/object'
2 |
3 | export const setWorkspaceAttrs = setAttrs('workspace');
4 |
--------------------------------------------------------------------------------
/src/components/capture.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import React from 'react';
17 |
18 | const eventNames = [
19 | 'onClick', 'onContextMenu', 'onDoubleClick', 'onDrag',
20 | 'onDragEnd', 'onDragEnter', 'onDragExit',
21 | 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop',
22 | 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp',
23 | ];
24 |
25 | export class AllowCapture extends React.Component {
26 | componentWillMount() {
27 | this.events = {};
28 | for (let n of eventNames) {
29 | this.events[n + 'Capture'] = e => {
30 | if (!this.capture)
31 | return;
32 | e.preventDefault();
33 | e.stopPropagation();
34 | if (this.capture.props[n])
35 | this.capture.props[n](e);
36 | };
37 | }
38 | this.events.onMouseDownCapture = e => {
39 | if (!this.capture)
40 | return;
41 | e.preventDefault();
42 | e.stopPropagation();
43 | if (this.capture.props.onMouseDown)
44 | this.capture.props.onMouseDown(e);
45 | }
46 | this.events.onMouseUpCapture = e => {
47 | if (!this.capture)
48 | return;
49 | e.preventDefault();
50 | e.stopPropagation();
51 | if (this.capture.props.onMouseUp)
52 | this.capture.props.onMouseUp(e);
53 | if (!e.buttons)
54 | this.capture = null;
55 | }
56 | this.events.onMouseLeave = e => {
57 | if (!this.capture)
58 | return;
59 | this.capture = null;
60 | }
61 | }
62 |
63 | getChildContext() {
64 | return { allowCapture: this };
65 | }
66 |
67 | render() {
68 | return (
69 |
70 | {this.props.children}
71 |
72 | );
73 | }
74 | };
75 | AllowCapture.childContextTypes = {
76 | allowCapture: React.PropTypes.any,
77 | };
78 |
79 | export default class Capture extends React.Component {
80 | componentWillMount() {
81 | this.onMouseDown = this.onMouseDown.bind(this);
82 | }
83 |
84 | onMouseDown(e) {
85 | this.context.allowCapture.capture = this;
86 | this.context.allowCapture.events.onMouseDownCapture(e);
87 | }
88 |
89 | render() {
90 | let {Component, style, onTouchStart, onTouchMove, onTouchEnd, onTouchCancel} = this.props;
91 | Component = Component || 'div';
92 | return (
93 |
96 | {this.props.children}
97 |
98 | );
99 | }
100 | };
101 | Capture.contextTypes = {
102 | allowCapture: React.PropTypes.any,
103 | };
104 |
--------------------------------------------------------------------------------
/src/components/dock.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Dock module.
3 | * @module
4 | */
5 |
6 | // React/Redux
7 | import React from 'react'
8 | import { connect } from 'react-redux'
9 |
10 | // Font awesome
11 | import Icon from './font-awesome'
12 |
13 | // Actions
14 | import * as actions from '../actions/panes'
15 |
16 | import { SettingsValidator } from './settings';
17 | import { CAMValidator } from './cam';
18 | /**
19 | * Dock item component.
20 | *
21 | * @extends module:react~React~Component
22 | * @param {Object} props Component properties.
23 | */
24 | class Button extends React.Component {
25 | /**
26 | * @type {Object}
27 | * @member module:components/dock~Button.prototype#props
28 | * @property {String} key Button key.
29 | * @property {String} title Button title.
30 | * @property {String} icon Button icon name (font-awesome).
31 | * @property {Boolean} active True if active button.
32 | * @property {module:components/dock~onButtonClick} onClick Called on dock item click.
33 | */
34 |
35 | /**
36 | * Render the component.
37 | * @return {String}
38 | */
39 | render() {
40 | let styleClasses=[];
41 | if (this.props.active) styleClasses.push('active');
42 | if (this.props.dimmed) styleClasses.push('dimmed');
43 | return (
44 |
45 |
46 |
47 | { this.props.title }
48 | {this.props.children}
49 |
50 |
51 | )
52 | }
53 | }
54 |
55 | /**
56 | * Dock component.
57 | * - Handle dock buttons.
58 | *
59 | * @extends module:react~React~Component
60 | * @param {Object} props Component properties.
61 | */
62 | class Dock extends React.Component {
63 | /**
64 | * @type {Object}
65 | * @member module:components/dock~Dock.prototype#props
66 | * @property {module:react~React~Component|module:react~React~Component[]} children Component children.
67 | * @property {module:components/dock~onButtonClick} onClick Called on dock item click.
68 | */
69 |
70 | /**
71 | * Render the component.
72 | * @return {String}
73 | */
74 | render() {
75 | return (
76 |
77 | {
78 | React.Children.map(this.props.children, item => {
79 |
80 | let validation;
81 | if (item.props.id=='settings') validation= ;
82 | if (item.props.id=='cam') validation= ;
83 |
84 | return this.props.onButtonClick(item.props.id)}
90 | >{validation}
91 | })
92 | }
93 |
94 | )
95 | }
96 | }
97 |
98 | const mapStateToProps = (state) => {
99 | return {
100 | selected: state.panes.selected,
101 | dimmed: !state.panes.visible,
102 | }
103 | }
104 |
105 | const mapDispatchToProps = (dispatch) => {
106 | return {
107 | /**
108 | * Called on dock item click.
109 | * - Select and set item ative.
110 | * @typedef {Function} module:components/dock~onButtonClick
111 | * @param {Integer} id Clicked item id.
112 | */
113 | onButtonClick: (id) => {
114 | dispatch(actions.selectPane(id))
115 | }
116 | }
117 | }
118 |
119 | // Exports
120 | export { Dock, Button }
121 | export default connect(mapStateToProps, mapDispatchToProps)(Dock)
122 |
--------------------------------------------------------------------------------
/src/components/dom3d.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | // Includes code from CSS3DRenderer.js:
17 | // Author mrdoob / http://mrdoob.com/
18 | // Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
19 |
20 | import { mat4 } from 'gl-matrix';
21 | import React from 'react'
22 |
23 | function epsilon(value) {
24 | return Math.abs(value) < Number.EPSILON ? 0 : value;
25 | };
26 |
27 | function getCameraCSSMatrix(matrix) {
28 | return 'matrix3d(' +
29 | epsilon(matrix[0]) + ',' +
30 | epsilon(- matrix[1]) + ',' +
31 | epsilon(matrix[2]) + ',' +
32 | epsilon(matrix[3]) + ',' +
33 |
34 | epsilon(matrix[4]) + ',' +
35 | epsilon(-matrix[5]) + ',' +
36 | epsilon(matrix[6]) + ',' +
37 | epsilon(matrix[7]) + ',' +
38 |
39 | epsilon(matrix[8]) + ',' +
40 | epsilon(-matrix[9]) + ',' +
41 | epsilon(matrix[10]) + ',' +
42 | epsilon(matrix[11]) + ',' +
43 |
44 | epsilon(matrix[12]) + ',' +
45 | epsilon(- matrix[13]) + ',' +
46 | epsilon(matrix[14]) + ',' +
47 | epsilon(matrix[15]) +
48 | ')';
49 | };
50 |
51 | export class Dom3d extends React.Component {
52 | componentWillUpdate(nextProps) {
53 | if (!nextProps.camera)
54 | return;
55 | let camera = nextProps.camera;
56 | if (camera.fovy) {
57 | this.fov = 0.5 * nextProps.height / Math.tan(camera.fovy * 0.5);
58 | this.transform = "translate3d(0,0," + this.fov + "px)" + getCameraCSSMatrix(camera.view) +
59 | " translate3d(" + nextProps.width / 2 + "px," + nextProps.height / 2 + "px, 0)";
60 | } else {
61 | this.transform = "scale(" + nextProps.width / 2 + "," + nextProps.height / 2 + ") " + getCameraCSSMatrix(camera.view) +
62 | " translate3d(" + nextProps.width / 2 + "px," + nextProps.height / 2 + "px, 0)";
63 | this.fov = 'none';
64 | }
65 | }
66 |
67 | render() {
68 | return (
69 |
74 |
81 | {this.props.children}
82 |
83 |
84 | );
85 | }
86 | }
87 |
88 | export class Text3d extends React.Component {
89 | shouldComponentUpdate(nextProps, nextState) {
90 | return (
91 | nextProps.x !== this.props.x ||
92 | nextProps.y !== this.props.y ||
93 | nextProps.size !== this.props.size ||
94 | nextProps.label !== this.props.label
95 | );
96 | }
97 |
98 | render() {
99 | return (
100 |
104 |
109 | {this.props.label || this.props.children}
110 |
111 |
112 | );
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/components/font-awesome.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Font-Awesome module.
3 | * @module
4 | */
5 |
6 | // React
7 | import React from 'react'
8 |
9 | /**
10 | * Communication component.
11 | *
12 | * @extends module:react~React~Component
13 | * @param {Object} props Component properties.
14 | */
15 | class Icon extends React.Component {
16 | /**
17 | * @type {Object}
18 | * @member module:components/font-awesome~Icon.prototype#props
19 | * @property {String} name Icon name (without fa- prefix)
20 | * @property {Boolean} fw If true display fixed width icon.
21 | */
22 |
23 | /**
24 | * Return the icon class name from props.
25 | * @return {String}
26 | */
27 | getClassName() {
28 | return 'fa fa-' + this.props.name + (this.props.fw ? ' fa-fw' : '')
29 | }
30 |
31 | /**
32 | * Render the component.
33 | * @return {String}
34 | */
35 | render() {
36 | return (
37 | this.props.name ? : null
38 | )
39 | }
40 | }
41 |
42 |
43 | // Exports
44 | export default Icon
45 |
--------------------------------------------------------------------------------
/src/components/get-bounds.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import React from 'react';
17 | import ReactDOM from 'react-dom';
18 |
19 | export class GetBounds extends React.Component {
20 | constructor() {
21 | super();
22 | this.state = {
23 | left: 0,
24 | top: 0,
25 | right: 0,
26 | bottom: 0,
27 | };
28 | }
29 |
30 | componentDidMount() {
31 | this.mounted = true;
32 | let f = () => {
33 | if (!this.mounted)
34 | return;
35 | let rect = ReactDOM.findDOMNode(this).getBoundingClientRect();
36 | let newState = {
37 | left: rect.left,
38 | top: rect.top,
39 | right: rect.right,
40 | bottom: rect.bottom,
41 | };
42 | if (newState.left !== this.state.left || newState.top !== this.state.top || newState.right !== this.state.right || newState.bottom !== this.state.bottom)
43 | this.setState(newState);
44 | requestAnimationFrame(f);
45 | };
46 | f();
47 | }
48 |
49 | componentWillUnmount() {
50 | this.mounted = false;
51 | }
52 |
53 | getChildContext() {
54 | return { bounds: this.state };
55 | }
56 |
57 | render() {
58 | let {Type, setBoundsProp, children, ...rest} = this.props;
59 | if (setBoundsProp)
60 | rest.bounds = this.state;
61 | return (
62 |
63 | {children}
64 |
65 | );
66 | }
67 | }
68 | GetBounds.childContextTypes = {
69 | bounds: React.PropTypes.any,
70 | };
71 |
72 | export function withGetBounds(Component) {
73 | class Wrapper extends React.Component {
74 | render() {
75 | return (
76 |
77 | {this.props.children}
78 |
79 | );
80 | }
81 | };
82 | return Wrapper;
83 | }
84 |
85 | export function withStoredBounds(Component) {
86 | class Wrapper extends React.Component {
87 | render() {
88 | return ;
89 | }
90 | };
91 | Wrapper.contextTypes = {
92 | bounds: React.PropTypes.any,
93 | };
94 | return Wrapper;
95 | }
96 |
--------------------------------------------------------------------------------
/src/components/keyboard.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import ReactDOM from 'react-dom';
4 | import keyboardJS from 'keyboardjs'
5 |
6 | export const keyboardLogger = keyboardJS;
7 |
8 | export const bindKeys=(keys, context='global')=>{
9 | keyboardLogger.withContext(context, () => {
10 | keys.forEach((entry)=>{
11 | let [keybinding,method] = entry;
12 | keyboardLogger.bind(keybinding.filter((i)=>(i!==undefined)),method)
13 | })
14 | })
15 | }
16 |
17 | export const unbindKeys=(keys)=>{
18 | keys.forEach((entry)=>{
19 | let [keybinding,method] = entry;
20 | keyboardLogger.unbind(keybinding.filter((i)=>(i!==undefined)),method)
21 | })
22 | }
23 |
24 | export const withKeyboardContext=(WrappedComponent, keyboardContext) =>{
25 | return class extends React.Component {
26 | constructor(props){
27 | super(props);
28 | this.__keyboardContext = 'global'
29 | this.handleMouseEnter = this.handleMouseEnter.bind(this);
30 | this.handleMouseLeave = this.handleMouseLeave.bind(this);
31 | }
32 |
33 | handleMouseEnter(e){
34 | if (keyboardLogger) {
35 | this.__keyboardContext=keyboardLogger.getContext();
36 | keyboardLogger.setContext(keyboardContext)
37 | console.log(keyboardContext)
38 | }
39 | }
40 |
41 | handleMouseLeave(e){
42 | if (keyboardLogger) {
43 | console.log(this.__keyboardContext )
44 | keyboardLogger.setContext(this.__keyboardContext || 'global')
45 | this.__keyboardContext = 'global';
46 |
47 | }
48 | }
49 |
50 | render() {
51 | return
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/components/omr.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Button } from 'react-bootstrap';
4 | import { connect } from 'react-redux';
5 |
6 | export class OmrJog extends React.Component {
7 |
8 | constructor(props){
9 | super(props)
10 | this.handleSetPosition = this.handleSetPosition.bind(this)
11 | }
12 |
13 | handleSetPosition(e) {
14 | if (this.props.onSetPosition)
15 | this.props.onSetPosition({x: this.props.settings.toolVideoOMROffsetX || 0, y: this.props.settings.toolVideoOMROffsetY || 0 });
16 | }
17 |
18 | render()
19 | {
20 | return
21 | OMR Set Position
22 |
23 | }
24 | }
25 |
26 | OmrJog = connect((state)=>{
27 | return { settings: state.settings }
28 | })(OmrJog)
--------------------------------------------------------------------------------
/src/components/panes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Panes module.
3 | * - Handle panes.
4 | * @module
5 | */
6 |
7 | // React/Redux
8 | import React from 'react'
9 | import { connect } from 'react-redux'
10 |
11 | /**
12 | * Pane component.
13 | *
14 | * @extends module:react~React~Component
15 | * @param {Object} props Component properties.
16 | */
17 | class Pane extends React.Component {
18 | /**
19 | * @type {Object}
20 | * @member module:components/pane~Pane.prototype#props
21 | * @property {String} key Pane key.
22 | * @property {String} title Pane title.
23 | * @property {String} icon Pane icon name (font-awesome).
24 | * @property {Boolean} active True if active button.
25 | * @property {module:react~React~Component|module:react~React~Component[]} children Component children.
26 | */
27 |
28 | /**
29 | * Render the component.
30 | * @return {String}
31 | */
32 | render() {
33 | return (
34 |
35 |
{ this.props.children }
36 |
37 | )
38 | }
39 | }
40 |
41 | /**
42 | * Panes component.
43 | * - Handle panes.
44 | *
45 | * @extends module:react~React~Component
46 | * @param {Object} props Component properties.
47 | */
48 | class Panes extends React.Component {
49 | shouldComponentUpdate(nextProps, nextState) {
50 | return nextProps.selected !== this.props.selected || nextProps.style.width !== this.props.style.width;
51 | }
52 |
53 | render() {
54 | return (
55 |
56 | {
57 | this.props.children
58 | .filter(item => item.props.id === this.props.selected)
59 | .map(item => (
60 |
66 | {item}
67 | ))
68 | }
69 |
70 | )
71 | }
72 | }
73 |
74 | const mapStateToProps = (state) => {
75 | return {
76 | selected: state.panes.selected,
77 | }
78 | }
79 |
80 | const mapDispatchToProps = (dispatch) => {
81 | return {}
82 | }
83 |
84 | // Exports
85 | export { Panes, Pane }
86 | export default connect(mapStateToProps, mapDispatchToProps)(Panes)
87 |
--------------------------------------------------------------------------------
/src/components/quote.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Quote module.
3 | * @module
4 | */
5 |
6 | // React
7 | import React from 'react'
8 |
9 | /**
10 | * Quote component.
11 | *
12 | * @extends module:react~React~Component
13 | * @param {Object} props Component properties.
14 | */
15 | class Quote extends React.Component {
16 | /**
17 | * Render the component.
18 | * @return {String}
19 | */
20 | render() {
21 | return (
22 |
25 | )
26 | }
27 | }
28 |
29 | // Exports
30 | export default Quote
31 |
--------------------------------------------------------------------------------
/src/components/setsize.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import React from 'react'
17 | import ReactDOM from 'react-dom';
18 | import omit from 'object.omit';
19 |
20 | export default class SetSize extends React.Component {
21 | constructor() {
22 | super();
23 | this.clientWidth = 1;
24 | this.clientHeight = 1;
25 | }
26 |
27 | componentDidMount() {
28 | this.mounted = true;
29 | let f = () => {
30 | if (!this.mounted)
31 | return;
32 | let node = ReactDOM.findDOMNode(this);
33 | if (this.props.selector && node.querySelector(this.props.selector))
34 | node = node.querySelector(this.props.selector)
35 | if (this.clientWidth !== node.clientWidth || this.clientHeight !== node.clientHeight) {
36 | this.clientWidth = node.clientWidth;
37 | this.clientHeight = node.clientHeight;
38 | this.setState({});
39 | }
40 | requestAnimationFrame(f);
41 | };
42 | f();
43 | }
44 |
45 | componentWillUnmount() {
46 | this.mounted = false;
47 | }
48 |
49 | render() {
50 | return (
51 |
52 | {React.cloneElement(this.props.children, { width: this.clientWidth, height: this.clientHeight })}
53 |
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/sidebar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sidebar module.
3 | * - Handle sidebar modules.
4 | * @module
5 | */
6 |
7 | // React/Redux
8 | import React from 'react'
9 | import { connect } from 'react-redux'
10 |
11 | // Main components
12 | import Dock from './dock'
13 | import Panes from './panes'
14 | import Splitter from './splitter';
15 |
16 | // Actions
17 | import * as panesActions from '../actions/panes'
18 |
19 | /**
20 | * Sidebar component.
21 | * - Handle sidebar modules.
22 | *
23 | * @extends module:react~React~Component
24 | * @param {Object} props Component properties.
25 | */
26 | class Sidebar extends React.Component {
27 | shouldComponentUpdate(nextProps, nextState) {
28 | return nextProps.visible !== this.props.visible;
29 | }
30 |
31 | render() {
32 | return (
33 |
42 | )
43 | }
44 | }
45 | Sidebar = connect(
46 | state => ({ visible: state.panes.visible })
47 | )(Sidebar);
48 |
49 | export default Sidebar
50 |
--------------------------------------------------------------------------------
/src/components/splitter.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import React from 'react';
17 | import { connect } from 'react-redux'
18 |
19 | import Capture from './capture';
20 | import { splitterSetSize } from '../actions/splitters'
21 |
22 | class Splitter extends React.Component {
23 | componentWillMount() {
24 | this.mouseDown = this.mouseDown.bind(this);
25 | this.touchStart = this.touchStart.bind(this);
26 | this.mouseMove = this.mouseMove.bind(this);
27 | this.touchMove = this.touchMove.bind(this);
28 | this.touchEnd = this.touchEnd.bind(this);
29 | }
30 |
31 | mouseDown(e) {
32 | this.mouseX = e.clientX;
33 | this.mouseY = e.clientY;
34 | }
35 |
36 | touchStart(e) {
37 | e.preventDefault();
38 | this.touching = true;
39 | let touch = e.changedTouches[0];
40 | this.mouseX = touch.clientX;
41 | this.mouseY = touch.clientY;
42 | }
43 |
44 | move(clientX, clientY) {
45 | let delta = this.props.split === 'horizontal' ? clientY - this.mouseY : clientX - this.mouseX;
46 | this.mouseX = clientX;
47 | this.mouseY = clientY;
48 | this.props.dispatch(splitterSetSize(this.props.splitterId, this.size + delta));
49 | this.forceUpdate();
50 | }
51 |
52 | mouseMove(e) {
53 | this.move(e.clientX, e.clientY);
54 | }
55 |
56 | touchMove(e) {
57 | e.preventDefault();
58 | let touch = e.changedTouches[0];
59 | if (this.touching)
60 | this.move(touch.clientX, touch.clientY);
61 | }
62 |
63 | touchEnd(e) {
64 | this.touching = false;
65 | }
66 |
67 | render() {
68 | this.size = this.props.splitters[this.props.splitterId];
69 | if (this.size === undefined)
70 | this.size = this.props.initialSize;
71 | if (this.props.minSize && this.size
75 | {React.cloneElement(
76 | this.props.children,
77 | {
78 | style: {
79 | ...this.props.children.props.style,
80 | [this.props.split === 'horizontal' ? 'height' : 'width']: this.size,
81 | }
82 | }
83 | )}
84 |
86 |
87 |
88 |
89 | );
90 | }
91 | }
92 |
93 | export default connect(
94 | state => ({ splitters: state.splitters }),
95 | )(Splitter);
96 |
--------------------------------------------------------------------------------
/src/components/subtree.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | // props:
4 | // objects: objects in forest
5 | // object: root
6 | // toggleExpanded: callback
7 | // Label: component which generates a label for an object (props.object contains object to render)
8 | // Right: component which generates right-hand side for an object (props.object contains object to render)
9 | // rowNumber: tracks current row across multiple calls for alternating line colors
10 | // indent: current indention level
11 | function Subtree(props) {
12 | let {
13 | objects,
14 | object,
15 | toggleExpanded = object => { },
16 | Label = ({object}) => Need a label ,
17 | Right = ({object}) => ,
18 | rowNumber = { value: 0 },
19 | indent = 0,
20 | selectedDocuments=[]
21 | } = props;
22 |
23 | return (
24 |
25 |
29 |
34 |
35 | toggleExpanded(object)}
37 | className={!object.children.length ? '' : object.expanded ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | {
46 | object.expanded ? object.children.map(childId => {
47 | let child = objects.find(child => child.id == childId);
48 | return (
49 |
50 | )
51 | }) : undefined
52 | }
53 |
54 |
55 | )
56 | };
57 |
58 | export default Subtree;
59 |
--------------------------------------------------------------------------------
/src/data/macros.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "*GotoXY0": {
4 | "label": "Goto XY zero",
5 | "gcode": "G0 X0Y0",
6 | "keybinding": "ctrl+f1",
7 | "_locked":false
8 | },
9 | "*LaserOff": {
10 | "label": "LASER OFF",
11 | "gcode": "M5",
12 | "keybinding": "ctrl+f2",
13 | "_locked":false
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/src/draw-commands/basic.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import { mat4 } from 'gl-matrix';
17 |
18 | export function basic(drawCommands) {
19 | let program = drawCommands.compile({
20 | vert: `
21 | precision mediump float;
22 | uniform mat4 perspective;
23 | uniform mat4 view;
24 | uniform vec3 scale;
25 | uniform vec3 translate;
26 | attribute vec3 position;
27 | void main() {
28 | gl_Position = perspective * view * vec4(scale * position + translate, 1);
29 | }`,
30 | frag: `
31 | precision mediump float;
32 | uniform vec4 color;
33 | void main() {
34 | gl_FragColor = color;
35 | }`,
36 | attrs: {
37 | position: { offset: 0 },
38 | },
39 | });
40 | return ({ perspective, view, scale, translate, color, primitive, position, offset, count }) => {
41 | drawCommands.execute({
42 | program,
43 | primitive,
44 | uniforms: { perspective, view, scale, translate, color },
45 | buffer: {
46 | data: position,
47 | stride: 12,
48 | offset: offset * 12,
49 | count,
50 | },
51 | });
52 | };
53 | }
54 |
55 | export function basic2d(drawCommands) {
56 | let program = drawCommands.compile({
57 | vert: `
58 | precision mediump float;
59 | uniform mat4 transform;
60 | attribute vec2 position;
61 | void main() {
62 | gl_Position = transform * vec4(position, 0.0, 1.0);
63 | }`,
64 | frag: `
65 | precision mediump float;
66 | uniform vec4 color;
67 | void main() {
68 | gl_FragColor = color;
69 | }`,
70 | attrs: {
71 | position: { offset: 0 },
72 | },
73 | });
74 | return ({ perspective, view, transform2d, color, primitive, position, offset, count }) => {
75 | let t = transform2d;
76 | let transform =
77 | mat4.multiply([], perspective,
78 | mat4.multiply([], view, [
79 | t[0], t[1], 0, 0,
80 | t[2], t[3], 0, 0,
81 | 0, 0, 1, 0,
82 | t[4], t[5], 0, 1]));
83 | drawCommands.execute({
84 | program,
85 | primitive,
86 | uniforms: { transform, color },
87 | buffer: {
88 | data: position,
89 | stride: 8,
90 | offset: offset * 8,
91 | count,
92 | },
93 | });
94 | };
95 | }
96 |
--------------------------------------------------------------------------------
/src/draw-commands/image.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | import { mat4 } from 'gl-matrix';
17 |
18 | export function image(drawCommands) {
19 | let program = drawCommands.compile({
20 | vert: `
21 | precision mediump float;
22 | uniform mat4 transform;
23 | uniform vec2 size;
24 | attribute vec2 position;
25 | varying vec2 coord;
26 | void main() {
27 | coord = position;
28 | gl_Position = transform * vec4(position * size, 0, 1);
29 | }`,
30 | frag: `
31 | precision mediump float;
32 | uniform sampler2D texture;
33 | uniform bool selected;
34 | uniform float alpha;
35 | varying vec2 coord;
36 | void main() {
37 | vec4 tex = texture2D(texture, vec2(coord.x, 1.0 - coord.y), 0.0);
38 | if(selected)
39 | tex = mix(tex, vec4(0.0, 0.0, 1.0, 1.0), .5);
40 | tex.a *= alpha;
41 | gl_FragColor = tex;
42 | }`,
43 | attrs: {
44 | position: { offset: 0 },
45 | },
46 | });
47 | let data = drawCommands.createBuffer(new Float32Array([0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0]));
48 | return ({ perspective, view, transform2d, texture, selected, alpha = 1 }) => {
49 | let t = transform2d;
50 | let transform =
51 | mat4.multiply([], perspective,
52 | mat4.multiply([], view, [
53 | t[0], t[1], 0, 0,
54 | t[2], t[3], 0, 0,
55 | 0, 0, 1, 0,
56 | t[4], t[5], 0, 1]));
57 | let size = [texture.width, texture.height];
58 | drawCommands.execute({
59 | program,
60 | primitive: drawCommands.gl.TRIANGLES,
61 | uniforms: { transform, size, texture, selected, alpha },
62 | buffer: {
63 | data,
64 | stride: 8,
65 | offset: 0,
66 | count: 6,
67 | },
68 | });
69 | };
70 | }
71 |
--------------------------------------------------------------------------------
/src/draw-commands/webcamfx.js:
--------------------------------------------------------------------------------
1 | export function pipeImage(drawCommands) {
2 | let program = drawCommands.compile({
3 | vert: `
4 | precision mediump float;
5 | attribute vec2 aPosition;
6 | varying vec2 uv;
7 | uniform float flipX;
8 | uniform float flipY;
9 | void main () {
10 | uv = aPosition;
11 | gl_Position = vec4(flipX + 2.0 * aPosition.x, flipY + 2.0 * aPosition.y, 0, 1);
12 | }
13 | `,
14 | frag: `
15 | precision mediump float;
16 | uniform sampler2D texture;
17 | varying vec2 uv;
18 | void main () {
19 | gl_FragColor = texture2D(texture, uv);
20 | }
21 | `,
22 | attrs: {
23 | aPosition: [
24 | -2, 0,
25 | 0, -2,
26 | 2, 2
27 | ]
28 | },
29 | });
30 |
31 | let data = drawCommands.createBuffer(new Float32Array([-2, 0, 0, -2, 2, 2]));
32 |
33 | return ({texture, flipX, flipY}) => {
34 | drawCommands.execute({
35 | program,
36 | primitive:drawCommands.gl.TRIANGLES,
37 | uniforms: {
38 | texture,
39 | flipX: flipX? -1.0 : 1.0,
40 | flipY: flipY? -1.0 : 1.0
41 | },
42 | buffer: {
43 | data,
44 | stride: 8,
45 | offset: 0,
46 | count: 3,
47 | },
48 | });
49 | };
50 | }
51 |
52 |
53 | export function barrelDistort(drawCommands) {
54 | let program = drawCommands.compile({
55 | frag: `
56 | #ifdef GL_ES
57 | precision highp float;
58 | #endif
59 |
60 | uniform vec4 uLens;
61 | uniform vec2 uFov;
62 |
63 | uniform sampler2D uSampler;
64 |
65 | varying vec3 vPosition;
66 | varying vec2 vTextureCoord;
67 |
68 | vec2 GLCoord2TextureCoord(vec2 glCoord) {
69 | return glCoord * vec2(1.0, 1.0)/ 2.0 + vec2(0.5, 0.5);
70 | }
71 |
72 | void main(void){
73 | float scale = uLens.w;
74 | float F = uLens.z;
75 |
76 | float L = length(vec3(vPosition.xy/scale, F));
77 |
78 | vec2 vMapping = vPosition.xy * F / L;
79 | vMapping = vMapping * uLens.xy;
80 |
81 | vMapping = GLCoord2TextureCoord(vMapping/scale);
82 |
83 | vec4 texture = texture2D(uSampler, vMapping);
84 | if(vMapping.x > 0.99 || vMapping.x < 0.01 || vMapping.y > 0.99 || vMapping.y < 0.01){
85 | texture = vec4(0.0, 0.0, 0.0, 1.0);
86 | }
87 | gl_FragColor = texture;
88 | }
89 | `,
90 | vert: `
91 | #ifdef GL_ES
92 | precision highp float;
93 | #endif
94 |
95 | attribute vec3 aVertexPosition;
96 |
97 | attribute vec2 aTextureCoord;
98 |
99 | varying vec3 vPosition;
100 | varying vec2 vTextureCoord;
101 |
102 | void main(void){
103 | vPosition = aVertexPosition;
104 | vTextureCoord = aTextureCoord;
105 |
106 | gl_Position = vec4(vPosition,1.0);
107 | }
108 | `,
109 | attrs: {
110 | aVertexPosition: [
111 | -1.0, -1.0, 0.0,
112 | 1.0, -1.0, 0.0,
113 | 1.0, 1.0, 0.0,
114 | -1.0, 1.0, 0.0
115 | ],
116 | aTextureCoord: [
117 | 0.0, 0.0,
118 | 1.0, 0.0,
119 | 1.0, 1.0,
120 | 0.0, 1.0
121 | ]
122 | },
123 | });
124 | let data = drawCommands.createBuffer(new Float32Array([
125 | -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
126 | -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
127 | 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0,
128 | -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0
129 | ]));
130 | return ({lens, fov, texture }) => {
131 | drawCommands.execute({
132 | program,
133 | primitive: drawCommands.gl.TRIANGLES,
134 | uniforms: { uLens: lens.map(parseFloat), uFov: fov.map(parseFloat), uSampler: texture },
135 | buffer: {
136 | data,
137 | stride: 20,
138 | offset: 0,
139 | count: 12,
140 | },
141 | });
142 | };
143 | }
144 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rack-Robotics/EDMWeb/6dbc8d877942cb9722d78b74effecb964fd16890/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | EDMWeb
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { compose, applyMiddleware, createStore } from 'redux';
4 | import { Provider } from 'react-redux';
5 | import { createLogger } from 'redux-logger';
6 |
7 | import persistState, {mergePersistedState} from 'redux-localstorage'
8 | import adapter from 'redux-localstorage/lib/adapters/localStorage';
9 | import filter from 'redux-localstorage-filter';
10 |
11 | export const LOCALSTORAGE_KEY = 'LaserWeb';
12 | export const DEBUG_KEY = "LaserwebDebug";
13 |
14 | const hot = (state, action) => {
15 | return require('./reducers').default(state, action);
16 | };
17 |
18 | const reducer = compose(
19 | mergePersistedState((initialState, persistedState) => {
20 | let state = { ...initialState, ...persistedState };
21 | state.camera = require('./reducers/camera').resetCamera(null, state.settings);
22 | return hot(state, { type: 'LOADED' });
23 | })
24 | )(hot);
25 |
26 | const storage = compose(
27 | filter(['settings','machineProfiles','splitters','materialDatabase'])
28 | )(adapter(window.localStorage));
29 |
30 |
31 | // adds getState() to any action to get the global Store :slick:
32 | const globalstoreMiddleWare = store => next => action => {
33 | next({ ...action, getState: store.getState });
34 | };
35 |
36 | export const getDebug = () =>{
37 | return window.localStorage.getItem(DEBUG_KEY)==='true';
38 | }
39 |
40 | export const setDebug=(b) => {
41 | window.localStorage.setItem(DEBUG_KEY,String(b))
42 | }
43 |
44 | const middlewares=[];
45 | if (getDebug()) middlewares.push(createLogger({ collapsed: true }))
46 | middlewares.push(globalstoreMiddleWare)
47 |
48 | const middleware = compose(
49 | applyMiddleware(...middlewares),
50 | persistState(storage, LOCALSTORAGE_KEY),
51 | );
52 |
53 | const store = createStore(reducer, middleware);
54 |
55 | // Bad bad bad
56 | export function GlobalStore()
57 | {
58 | return store;
59 | }
60 |
61 | function Hot(props) {
62 | const LaserWeb = require('./components/laserweb').default;
63 | return ;
64 | }
65 |
66 | function renderHot() {
67 | render((
68 |
69 |
70 |
71 | ), document.getElementById('laserweb'));
72 | }
73 | renderHot();
74 |
75 | if (module.hot) {
76 | module.hot.accept('./reducers', renderHot);
77 | module.hot.accept('./components/laserweb', renderHot);
78 | }
79 |
--------------------------------------------------------------------------------
/src/lib/action2gcode/gcode-generator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import DefaultGenerator from "./generators/default-generator"
4 | import MarlinGenerator from "./generators/marlin-generator"
5 |
6 | export function getGenerator(gcodeGenerator, settings) {
7 | switch(gcodeGenerator){
8 | case "marlin" :
9 | return new MarlinGenerator(settings);
10 | case "default" :
11 | default :
12 | return new DefaultGenerator(settings);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/action2gcode/generators/abstract-generator.js:
--------------------------------------------------------------------------------
1 | import XRegExp from 'xregexp';
2 |
3 | // AbstractDriver class
4 | class AbstractGenerator {
5 | // Class constructor...
6 | constructor(settings) {
7 | this.settings = settings;
8 | }
9 |
10 | postProcessRaster(gcode){
11 | if (this.settings.gcodeToolOn && this.settings.gcodeToolOff){
12 | gcode = XRegExp.replace(gcode,new XRegExp("G0(.*?)G1","gis"),'G0$1\n'+this.settings.gcodeToolOn+'\nG1')
13 | gcode = XRegExp.replace(gcode,new XRegExp("G1(.*?)G0","gis"),'G1$1\n'+this.settings.gcodeToolOff+'\nG0')
14 | return gcode;
15 | //return gcode.replace(new XRegExp("G0(.*?)G1","gis"),'G0$1\n'+this.settings.gcodeToolOn+'\nG1').replace(new XRegExp("G1(.*?)G0","gis"),'G1$1\n'+this.settings.gcodeToolOff+'\nG0')
16 | }
17 | return gcode;
18 | }
19 |
20 | }
21 |
22 | // Exports
23 | export { AbstractGenerator }
24 | export default AbstractGenerator
25 |
--------------------------------------------------------------------------------
/src/lib/action2gcode/generators/default-generator.js:
--------------------------------------------------------------------------------
1 |
2 | import AbstractGenerator from "./abstract-generator"
3 |
4 | // AbstractDriver class
5 | class DefaultGenerator extends AbstractGenerator{
6 | // Class constructor...
7 | constructor(settings) {
8 | super(settings);
9 | }
10 |
11 | moveRapid(params, optimized=false){
12 | if(params == null)
13 | return "";
14 |
15 | let gcode = "";
16 | if(!optimized) gcode+="G0 ";
17 | gcode += this.move(params);
18 | return gcode;
19 | }
20 |
21 | moveTool(params, optimized=false){
22 | if(params == null)
23 | return "";
24 |
25 | let gcode = "";
26 | if(!optimized) gcode+="G1 ";
27 | gcode += this.move(params);
28 | return gcode;
29 | }
30 |
31 | toolOn(gcode, params){
32 | if(gcode == null)
33 | return "";
34 |
35 | if(params.hasOwnProperty("i"))
36 | gcode = gcode.split("$INTENSITY").join(params.i);
37 | return gcode;
38 | }
39 |
40 | toolOff(gcode, params){
41 | if(gcode == null)
42 | return "";
43 |
44 | if(params.hasOwnProperty("i"))
45 | gcode = gcode.split("$INTENSITY").join(params.i);
46 | return gcode;
47 | }
48 |
49 | move(params){
50 | let gcode = "";
51 | if(params.hasOwnProperty("x"))
52 | gcode += ` X${params.x}`;
53 |
54 | if(params.hasOwnProperty("y"))
55 | gcode += ` Y${params.y}`;
56 |
57 | if(params.hasOwnProperty("a"))
58 | gcode += ` A${params.a}`;
59 |
60 | if(params.hasOwnProperty("i"))
61 | gcode += ` ${params.i}`;
62 |
63 | if(params.hasOwnProperty("s"))
64 | gcode += ` S${params.s}`;
65 |
66 | if(params.hasOwnProperty("f"))
67 | gcode += ` F${params.f}`;
68 |
69 | return gcode.trim();
70 | }
71 |
72 | }
73 |
74 | // Exports
75 | export { DefaultGenerator }
76 | export default DefaultGenerator
77 |
--------------------------------------------------------------------------------
/src/lib/action2gcode/generators/marlin-generator.js:
--------------------------------------------------------------------------------
1 |
2 | import AbstractGenerator from "./abstract-generator"
3 |
4 | // AbstractDriver class
5 | class MarlinGenerator extends AbstractGenerator{
6 | // Class constructor...
7 | constructor(settings) {
8 | super(settings);
9 | }
10 |
11 | moveRapid(params, optimized=false){
12 | if(params == null)
13 | return "";
14 |
15 | return this.move("G0", params);
16 | }
17 |
18 | moveTool(params, optimized=false){
19 | if(params == null)
20 | return "";
21 |
22 | return this.move("G1", params);
23 | }
24 |
25 | toolOn(gcode, params){
26 | if(gcode == null)
27 | return "";
28 |
29 | if(params.hasOwnProperty("i"))
30 | gcode = gcode.split("$INTENSITY").join(params.i);
31 | return gcode;
32 | }
33 |
34 | toolOff(gcode, params){
35 | if(gcode == null)
36 | return "";
37 |
38 | if(params.hasOwnProperty("i"))
39 | gcode = gcode.split("$INTENSITY").join(params.i);
40 | return gcode;
41 | }
42 |
43 | move(prefix, params){
44 | let gcode = "";
45 |
46 | if(params.hasOwnProperty("s")){
47 | if(this.settings.gcodeToolOn.indexOf("$INTENSITY") > -1){
48 | gcode += `${this.settings.gcodeToolOn.split("$INTENSITY").join(this.settings.gcodeLaserIntensity+params.s)}\r\n`;
49 | }else{
50 | gcode += `${this.settings.gcodeToolOn} S${params.s}\r\n`;
51 | }
52 | }
53 |
54 | if(params.hasOwnProperty("i")){
55 | if(this.settings.gcodeToolOn.indexOf("$INTENSITY") > -1){
56 | gcode += `${this.settings.gcodeToolOn.split("$INTENSITY").join(params.i)}\r\n`;
57 | }else{
58 | gcode += `${this.settings.gcodeToolOn} ${params.i}\r\n`;
59 | }
60 | }
61 |
62 | gcode += prefix;
63 |
64 | if(params.hasOwnProperty("x"))
65 | gcode += ` X${params.x}`;
66 |
67 | if(params.hasOwnProperty("y"))
68 | gcode += ` Y${params.y}`;
69 |
70 | if(params.hasOwnProperty("a"))
71 | gcode += ` A${params.a}`;
72 |
73 | if(params.hasOwnProperty("f"))
74 | gcode += ` F${params.f}`;
75 |
76 | return gcode.trim();
77 | }
78 |
79 | }
80 |
81 | // Exports
82 | export { MarlinGenerator }
83 | export default MarlinGenerator
84 |
--------------------------------------------------------------------------------
/src/lib/helpers.js:
--------------------------------------------------------------------------------
1 |
2 | import objectToString from 'object-to-string';
3 |
4 | export function sendAsFile(filename, data, mimetype) {
5 | let blob = new Blob([data], {type: mimetype});
6 |
7 | let tempLink = document.createElement('a');
8 | tempLink.href = window.URL.createObjectURL(blob);
9 | tempLink.setAttribute('download', filename);
10 | tempLink.click();
11 | }
12 |
13 | export function appendExt(filename, ext) {
14 | return (!filename.match(new RegExp(ext.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')+"$",'gi'))) ? (filename+ext):filename;
15 | }
16 |
17 | // This is the function that is ultimately called by the Generate gocde button
18 | export function openDataWindow(data, mimetype='text/plain;charset=utf-8', target="data")
19 | {
20 | console.log(data);s
21 | let blob = new Blob([data], {type: mimetype});
22 | let reader = new FileReader();
23 | reader.onloadend = function(e) {
24 | window.open(reader.result,target);
25 | }
26 | reader.readAsDataURL(blob);
27 | }
28 |
29 | export function isObject(item) {
30 | return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
31 | }
32 |
33 | export function deepMerge(target, source) {
34 | let output = Object.assign({}, target);
35 | if (isObject(target) && isObject(source)) {
36 | Object.keys(source).forEach(key => {
37 | if (isObject(source[key])) {
38 | if (!(key in target))
39 | Object.assign(output, { [key]: source[key] });
40 | else
41 | output[key] = deepMerge(target[key], source[key]);
42 | } else {
43 | Object.assign(output, { [key]: source[key] });
44 | }
45 | });
46 | }
47 | return output;
48 | }
49 |
50 | export function getDescendantProp(obj, desc) {
51 | var arr = desc.split(".");
52 | while(arr.length && (obj = obj[arr.shift()]));
53 | return obj;
54 | }
55 |
56 | export function cast(value, def = '') {
57 | if (value === undefined) return def;
58 | if (value === false) return "No";
59 | if (value === true) return "Yes";
60 | if (isObject(value)) return objectToString(value);
61 | return String(value);
62 | }
63 |
64 | export function clamp(num, min, max) {
65 | return num <= min ? min : num >= max ? max : num;
66 | }
67 |
68 |
69 | export const captureConsole = () => {
70 |
71 | window.__capture=window.console;
72 | let captures=[];
73 |
74 | window.console = {
75 | log(...args){
76 | captures.push({method:"log",args})
77 | },
78 |
79 | warn(...args){
80 | captures.push({method:"warn",args})
81 | },
82 |
83 | error(...args){
84 | captures.push({method:"error",args})
85 | },
86 |
87 | info(...args){
88 | captures.push({method:"info",args})
89 | }
90 | }
91 |
92 | return (keys=[])=>{
93 | window.console = window.__capture;
94 | if (keys === true) keys=['log','warn','error','info']
95 | if (keys.length){
96 |
97 | captures.forEach(item => {
98 | if (keys.includes(item.method)) {
99 | window.console[item.method].apply(null, item.args)
100 | }
101 | })
102 | }
103 |
104 | return captures;
105 | }
106 |
107 | }
108 |
109 | export const strtr=(str,reps)=>{
110 | Object.entries(reps).forEach((entry)=>{
111 | str=str.replace(entry[0],entry[1])
112 | })
113 | return str;
114 | }
--------------------------------------------------------------------------------
/src/lib/material-database.js:
--------------------------------------------------------------------------------
1 | import { flatten, unflatten } from 'flat';
2 | import prefixKeys from 'prefix-keys';
3 | import stringify from 'json-stringify-pretty-compact'
4 |
5 | import { OPERATION_TYPES, OPERATION_FIELDS } from '../components/operation';
6 | import omit from "object.omit";
7 |
8 | export function materialTreeToTabular(materials) {
9 |
10 | let data = {};
11 | let paramkeys = []
12 | //stage 1 - extract all operation keys.
13 | materials.forEach((materialRow) => {
14 | materialRow.operations.forEach((operation, i) => {
15 | paramkeys = [...paramkeys, ...OPERATION_TYPES[operation.type].fields].filter((item, pos, obj) => { return obj.indexOf(item) == pos })
16 | })
17 | })
18 | //stage 2 - defaults, prefix & flatten.
19 | materials.forEach((materialRow) => {
20 | let row;
21 | if (materialRow.operations.length) {
22 | materialRow.operations.forEach((operation, i) => {
23 | let params = {}
24 | paramkeys.forEach((opfield) => {
25 | params[opfield] = operation.params[opfield] = operation.params[opfield] || null
26 | })
27 |
28 | row = Object.assign({}, { id: materialRow.id },
29 | prefixKeys('material.', flatten(omit(materialRow.material, ['isOpened']))),
30 | prefixKeys('operation.', flatten(omit(operation, ['params', 'isEditable']))),
31 | prefixKeys('operation.params.', flatten(params))
32 | )
33 | })
34 | } else {
35 | row = Object.assign({}, { id: materialRow.id }, prefixKeys('material.', flatten(omit(materialRow.material, ['isOpened']))))
36 | }
37 |
38 | Object.entries(row).forEach((entry, j) => {
39 | let [key, value] = entry;
40 | data[key] = data[key] || [];
41 | data[key].push(value)
42 | })
43 |
44 | });
45 |
46 |
47 | // stage 3 - transpose
48 | let result = Object.entries(data).map((item) => {
49 | let [key, values] = item;
50 | return [key, ...values];
51 | })
52 |
53 | const transpose = (a) => { return a[0].map((_, c) => { return a.map((r) => { return r[c]; }); }) };
54 |
55 |
56 | return transpose(result)
57 |
58 |
59 |
60 | }
61 |
62 |
63 | export function materialTabularToTree(tab) {
64 |
65 | let keys = [];
66 | let tree = [];
67 |
68 | // stage 1 - zip rows
69 | let list = csv2arr(tab).map((row, i, obj) => {
70 | if (!i) {
71 | keys = row;
72 | } else {
73 | let rowobj = {}
74 | keys.forEach((col, j) => { rowobj[col] = row[j] })
75 | return rowobj;
76 | }
77 | })
78 |
79 | // stage 2 - extract operation indexes
80 | let lastmaterial;
81 | list.forEach((row, i, obj) => {
82 | let material = unflatten(row);
83 |
84 | if (!i) lastmaterial = material;
85 |
86 | if (material.id != lastmaterial.id) {
87 | tree.push(lastmaterial)
88 | tree.push(material)
89 | lastmaterial = material;
90 | }
91 |
92 | lastmaterial.operations = lastmaterial.operations || [];
93 | lastmaterial.operations.push(Object.assign({}, material.operation));
94 |
95 | delete lastmaterial.operation
96 | })
97 |
98 | return tree;
99 |
100 | }
101 |
102 | export function arr2csv(arr, delimiter = ',', enclose = '"', linebreak = "\r\n") {
103 | return arr.map((row) => { return enclose + row.join(enclose + delimiter + enclose) + enclose }).join(linebreak);
104 | }
105 |
106 | export function csv2arr(csv, delimiter = ',', enclose = '"', linebreak = /[\r\n]+/gi) {
107 | enclose = enclose || "";
108 | return csv.split(linebreak).map((row) => {
109 | return row.split(new RegExp('\\' + enclose + '\\' + delimiter + '\\' + enclose, 'gi')).map((column) => { return column.replace(new RegExp('^\\' + enclose + '|\\' + enclose + '$', "gi"), "") })
110 | });
111 | }
--------------------------------------------------------------------------------
/src/lib/omr.js:
--------------------------------------------------------------------------------
1 | import AR from './js-aruco/aruco.js';
2 | import POS from './js-aruco/posit2.js';
3 |
4 | const DEFAULT_MODEL_SIZE = 20
5 |
6 | export const arucoProcess= (canvas, settings) => {
7 | const context= canvas.getContext('2d');
8 | const model_size = settings.toolVideoOMRMarkerSize || DEFAULT_MODEL_SIZE;
9 | const detector = new AR.Detector();
10 |
11 |
12 | let imageData = context.getImageData(0, 0, canvas.width, canvas.height);
13 | let markers = detector.detect(imageData);
14 |
15 | drawCorners(markers,canvas);
16 | let pose = getPose(markers,model_size,canvas);
17 | if (pose) drawPose(pose.bestError, pose.bestRotation, pose.bestTranslation,canvas);
18 |
19 | return canvas;
20 |
21 | }
22 |
23 | const drawCorners = (markers, canvas)=> {
24 | const context= canvas.getContext('2d');
25 | var corners, corner, i, j;
26 |
27 | context.lineWidth = 3;
28 | for (i = 0; i < markers.length; ++ i){
29 | corners = markers[i].corners;
30 |
31 | context.strokeStyle = "red";
32 | context.beginPath();
33 |
34 | for (j = 0; j < corners.length; ++ j){
35 | corner = corners[j];
36 | context.moveTo(corner.x, corner.y);
37 | corner = corners[(j + 1) % corners.length];
38 | context.lineTo(corner.x, corner.y);
39 | }
40 | context.stroke();
41 | context.closePath();
42 |
43 | context.strokeStyle = "green";
44 | context.strokeRect(corners[0].x - 2, corners[0].y - 2, 4, 4);
45 |
46 | context.fillStyle = "blue";
47 | context.font="30px Arial";
48 | context.fillText(markers[i].id, corners[0].x, corners[0].y)
49 | }
50 | context.save();
51 | };
52 |
53 | const getPose = (markers, model_size, canvas)=>{
54 | const posit = new POS.Posit(model_size, canvas.width);
55 | var corners, corner, pose, i;
56 | if (markers.length > 0){
57 | corners = markers[0].corners;
58 | for (i = 0; i < corners.length; ++ i){
59 | corner = corners[i];
60 | corner.x = corner.x - (canvas.width / 2);
61 | corner.y = (canvas.height / 2) - corner.y;
62 | }
63 | return posit.pose(corners);
64 | }
65 | return null;
66 | }
67 |
68 | function drawPose(error, rotation, translation,canvas){
69 | var yaw = -Math.atan2(rotation[0][2], rotation[2][2]);
70 | var pitch = -Math.asin(-rotation[1][2]);
71 | var roll = Math.atan2(rotation[1][0], rotation[1][1]);
72 |
73 | let data = {
74 | x: translation[0] | 0,
75 | y: translation[1] | 0,
76 | z: translation[2] | 0,
77 | yaw: Math.round(-yaw * 180.0/Math.PI),
78 | pitch: Math.round(-pitch * 180.0/Math.PI),
79 | roll: Math.round(roll * 180.0/Math.PI)
80 | }
81 |
82 | const context = canvas.getContext('2d');
83 |
84 | context.fillStyle="fuchsia";
85 | context.font="20px Arial";
86 | context.fillText(`x: ${data.x}, y: ${data.y}, z: ${data.z}`, 0,20);
87 | context.fillText(`yaw: ${data.yaw}, pitch: ${data.pitch}, roll: ${data.roll}`, 0,40);
88 |
89 | };
--------------------------------------------------------------------------------
/src/lib/redux-action.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Dock actions.
3 | * @module
4 | */
5 |
6 | /**
7 | * Flux standard action.
8 | * @see {@link https://github.com/acdlite/flux-standard-action|flux-standard-action}.
9 | * @typedef {Object} module:lib/redux-action~Action
10 | * @property {String} type Action type (eg.: "ADD_SOMETHING").
11 | * @property {mixed} [payload] It represents the payload of the action. If the payload is an instance of Error the error property is set to true.
12 | * @property {mixed} [meta] It is intended for any extra information.
13 | * @property {Boolean} [error] True if an error occured. If true the payload must be an Error instance.
14 | */
15 |
16 | /**
17 | * Create and return an action creator.
18 | * @function
19 | * @param {String} type Action type (eg.: "ADD_SOMETHING").
20 | * @param {...String} [argsNames] Action creator arguments names.
21 | * @return {module:lib/redux-action~ActionCreator} Action creator.
22 | */
23 | function actionCreatorFactory(type, ...argsNames) {
24 | /**
25 | * Create and return an action.
26 | * @typedef {Function} module:lib/redux-action~ActionCreator
27 | * @param {...args} [args] Action arguments (to map with argsNames).
28 | * @return {module:lib/redux-action~Action} The created action.
29 | */
30 | let actionCreator = function(...args) {
31 | let meta = undefined
32 | let error = undefined
33 | let payload = undefined
34 |
35 | if (args.length && args[0] instanceof Error) {
36 | meta = args.splice(1, args.length - 1)
37 | payload = args[0]
38 | error = true
39 | }
40 | else {
41 | if (! argsNames.length) {
42 | payload = args.length ? args.shift() : payload
43 | }
44 |
45 | meta = args.splice(argsNames.length, args.length - argsNames.length)
46 | payload = args.length ? {} : payload
47 | }
48 |
49 | if (meta.length === 0) {
50 | meta = undefined
51 | }
52 | else if (meta.length === 1) {
53 | meta = meta[0]
54 | }
55 |
56 | let action = { type, payload, error, meta }
57 |
58 | if (payload !== undefined && argsNames.length) {
59 | argsNames.forEach((arg, index) => {
60 | action.payload[argsNames[index]] = args[index]
61 | })
62 | }
63 |
64 | return action
65 | }
66 |
67 | actionCreator.TYPE = type
68 |
69 | return actionCreator
70 | }
71 |
72 | // Exports
73 | export default actionCreatorFactory
74 |
--------------------------------------------------------------------------------
/src/lib/releases.js:
--------------------------------------------------------------------------------
1 | import { strtr } from './helpers';
2 |
3 | const API_CHECK_URL='https://api.github.com/repos/:owner/:repo/releases/latest';
4 | const API_OWNER='Rack-Robotics'
5 | const API_REPO='EDMWeb-Binaries'
6 |
7 |
8 |
9 | export const fetchRelease=()=>{
10 | return new Promise((resolve,reject)=>{
11 | if (!window.fetch) {
12 | reject('No fetch available');
13 | } else {
14 | let url=strtr(API_CHECK_URL,{':owner':API_OWNER, ':repo':API_REPO});
15 | fetch(url).then((response)=>{
16 | response.json().then((json)=>{
17 | resolve(json);
18 | }).catch((error)=>{
19 | reject(error)
20 | })
21 | }).catch((error)=>{
22 | reject(error);
23 | })
24 | }
25 | })
26 | }
--------------------------------------------------------------------------------
/src/lib/storages.js:
--------------------------------------------------------------------------------
1 | import { sendAsFile, appendExt } from './helpers';
2 |
3 |
4 | /* Yes, I know, got to switch to promises but I can't promise that.*/
5 | class FileStorageAdapter {
6 |
7 | load(file, onload = () => { }) {
8 | let reader = new FileReader;
9 | reader.onload = () => onload(file, reader.result);
10 | reader.readAsText(file);
11 | }
12 |
13 | save(name, data, mime, extension, ...rest) {
14 | if (extension) name=appendExt(name, extension);
15 | sendAsFile(name, data, mime);
16 | }
17 | }
18 |
19 | class LocalStorageAdapter {
20 |
21 | load(key, onload = () => { }) {
22 | onload(key, localStorage.getItem(key))
23 | }
24 |
25 | save(key, data, ...rest) {
26 | localStorage.setItem(key, data);
27 | }
28 |
29 | }
30 |
31 |
32 | export let FileStorage = new FileStorageAdapter();
33 |
34 | export let LocalStorage = new LocalStorageAdapter();
--------------------------------------------------------------------------------
/src/lib/tmpParseGcode.js:
--------------------------------------------------------------------------------
1 | // Copyright 2014, 2016, 2017 Todd Fleming
2 | //
3 | // This program is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU Affero General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU Affero General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU Affero General Public License
14 | // along with this program. If not, see .
15 |
16 | 'use strict';
17 |
18 | export function parseGcode(gcode) {
19 | let path = [];
20 | let lastG = NaN, lastX = NaN, lastY = NaN, lastZ = NaN, lastA = NaN, lastF = NaN, lastS = 0, lastT = 0;
21 | let stride = 9;
22 | let i = 0;
23 | while (i < gcode.length) {
24 | function parse() {
25 | ++i;
26 | while (i < gcode.length && (gcode[i] == ' ' || gcode[i] == '\t'))
27 | ++i;
28 | let begin = i;
29 | while (i < gcode.length && "+-.0123456789".indexOf(gcode[i]) != -1)
30 | ++i;
31 | return Number(gcode.substr(begin, i - begin));
32 | }
33 | let g = NaN, x = NaN, y = NaN, z = NaN, a = NaN, f = NaN;
34 | while (i < gcode.length && gcode[i] != ';' && gcode[i] != '\r' && gcode[i] != '\n') {
35 | if (gcode[i] == 'G' || gcode[i] == 'g')
36 | g = parse();
37 | else if (gcode[i] == 'X' || gcode[i] == 'x')
38 | x = parse();
39 | else if (gcode[i] == 'Y' || gcode[i] == 'y')
40 | y = parse();
41 | else if (gcode[i] == 'Z' || gcode[i] == 'z')
42 | z = parse();
43 | else if (gcode[i] == 'A' || gcode[i] == 'a')
44 | a = parse();
45 | else if (gcode[i] == 'F' || gcode[i] == 'f')
46 | f = parse();
47 | else if (gcode[i] == 'S' || gcode[i] == 's')
48 | lastS = parse();
49 | else if (gcode[i] == 'T' || gcode[i] == 't')
50 | lastT = parse();
51 | else
52 | ++i;
53 | }
54 | if (g === 0 || g === 1 || !isNaN(x) || !isNaN(y) || !isNaN(z) || !isNaN(a)) {
55 | if (g === 0 || g === 1)
56 | lastG = g;
57 | if (!isNaN(x)) {
58 | if (isNaN(lastX))
59 | for (let j = 1; j < path.length; j += stride)
60 | path[j] = x;
61 | lastX = x;
62 | }
63 | if (!isNaN(y)) {
64 | if (isNaN(lastY))
65 | for (let j = 2; j < path.length; j += stride)
66 | path[j] = y;
67 | lastY = y;
68 | }
69 | if (!isNaN(z)) {
70 | if (isNaN(lastZ))
71 | for (let j = 3; j < path.length; j += stride)
72 | path[j] = z;
73 | lastZ = z;
74 | }
75 | if (!isNaN(a)) {
76 | if (isNaN(lastA))
77 | for (let j = 6; j < path.length; j += stride)
78 | path[j] = a;
79 | lastA = a;
80 | }
81 | if (!isNaN(f)) {
82 | if (isNaN(lastF))
83 | for (let j = 4; j < path.length; j += stride)
84 | path[j] = f;
85 | lastF = f;
86 | }
87 | if (!isNaN(lastG)) {
88 | path.push(lastG);
89 | path.push(lastX);
90 | path.push(lastY);
91 | path.push(lastZ);
92 | path.push(0); // E
93 | path.push(lastF);
94 | path.push(lastA);
95 | path.push(lastS);
96 | path.push(lastT);
97 | }
98 | }
99 | while (i < gcode.length && gcode[i] != '\r' && gcode[i] != '\n')
100 | ++i;
101 | while (i < gcode.length && (gcode[i] == '\r' || gcode[i] == '\n'))
102 | ++i;
103 | }
104 |
105 | if (isNaN(lastX))
106 | for (let j = 1; j < path.length; j += stride)
107 | path[j] = 0;
108 | if (isNaN(lastY))
109 | for (let j = 2; j < path.length; j += stride)
110 | path[j] = 0;
111 | if (isNaN(lastZ))
112 | for (let j = 3; j < path.length; j += stride)
113 | path[j] = 0;
114 | if (isNaN(lastF))
115 | for (let j = 4; j < path.length; j += stride)
116 | path[j] = 1000;
117 | if (isNaN(lastA))
118 | for (let j = 6; j < path.length; j += stride)
119 | path[j] = 0;
120 |
121 | return path;
122 | }
123 |
--------------------------------------------------------------------------------
/src/lib/util.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | export function objectHasMatchingFields(obj, fields) {
4 | for (let key in fields)
5 | if (fields.hasOwnProperty(key) && obj[key] !== fields[key])
6 | return false;
7 | return true;
8 | }
9 |
10 | export function sameArrayContent(a, b) {
11 | return a.length === b.length && a.every((v, i) => v === b[i])
12 | }
13 |
--------------------------------------------------------------------------------
/src/lib/workers/cam-lasercut.js:
--------------------------------------------------------------------------------
1 | import { getLaserCutGcodeFromOp } from '../cam-gcode-laser-cut'
2 |
3 | onmessage = (event) => {
4 |
5 | let {settings, opIndex, op, geometry = [], openGeometry = [], tabGeometry = []} = event.data
6 |
7 | const errors = [];
8 |
9 | const showAlert = (message, level) => {
10 | errors.push({ message, level })
11 | };
12 | const progress = () => {
13 | postMessage(JSON.stringify({ event: "onProgress", gcode, errors }))
14 | };
15 | const done = (gcode) => {
16 | if (gcode === false && errors.length) {
17 | postMessage(JSON.stringify({ event: "onError", errors }))
18 | } else {
19 | postMessage(JSON.stringify({ event: "onDone", gcode }))
20 | }
21 | self.close();
22 | };
23 |
24 | try{
25 | getLaserCutGcodeFromOp.apply(this, [settings, opIndex, op, geometry, openGeometry, tabGeometry, showAlert, done, progress])
26 | }catch(e){
27 | console.error(e);
28 | postMessage(JSON.stringify({ event: "onError", errors:[{ message:e, level:10 }]}));
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/src/lib/workers/cam-lathe.js:
--------------------------------------------------------------------------------
1 | import { getLatheGcodeFromOp } from '../cam-gcode-lathe'
2 |
3 | onmessage = (event) => {
4 | const { settings, opIndex, op, geometry = [], openGeometry = [], tabGeometry = [] } = event.data
5 | const errors = [];
6 |
7 | const showAlert = (message, level) => {
8 | errors.push({ message, level })
9 | };
10 | const progress = () => {
11 | postMessage(JSON.stringify({ event: "onProgress", gcode, errors }))
12 | };
13 | const done = (gcode) => {
14 | if (gcode === false && errors.length) {
15 | postMessage(JSON.stringify({ event: "onError", errors }))
16 | } else {
17 | postMessage(JSON.stringify({ event: "onDone", gcode }))
18 | }
19 | };
20 |
21 | getLatheGcodeFromOp.apply(this, [settings, opIndex, op, geometry, openGeometry, tabGeometry, showAlert, done, progress])
22 | }
23 |
--------------------------------------------------------------------------------
/src/lib/workers/cam-mill.js:
--------------------------------------------------------------------------------
1 | import { getMillGcodeFromOp } from '../cam-gcode-mill'
2 |
3 | onmessage = (event) => {
4 |
5 | const {settings, opIndex, op, geometry=[], openGeometry=[], tabGeometry=[]} = event.data
6 | const errors = [];
7 |
8 | const showAlert = (message, level) => {
9 | errors.push({ message, level })
10 | };
11 | const progress = () => {
12 | postMessage(JSON.stringify({ event: "onProgress", gcode, errors }))
13 | };
14 | const done = (gcode) => {
15 | if (gcode === false && errors.length) {
16 | postMessage(JSON.stringify({ event: "onError", errors }))
17 | } else {
18 | postMessage(JSON.stringify({ event: "onDone", gcode }))
19 | }
20 | };
21 |
22 | getMillGcodeFromOp.apply(this, [settings, opIndex, op, geometry, openGeometry, tabGeometry, showAlert, done, progress])
23 |
24 | }
--------------------------------------------------------------------------------
/src/lib/workers/cam-preflight.js:
--------------------------------------------------------------------------------
1 | import { rawPathsToClipperPaths, union, xor } from '../mesh';
2 |
3 |
4 | self.onmessage = (event) => {
5 |
6 | const jobs = [];
7 |
8 | let { settings, opIndex, op, geometry, openGeometry, tabGeometry, documents } = event.data;
9 |
10 | const filteredDocIds = new Set();
11 | const docsWithImages = []
12 |
13 | function matchColor(filterColor, color) {
14 | if (!filterColor)
15 | return true;
16 | if (!color)
17 | return false;
18 | return filterColor[0] == color[0] && filterColor[1] == color[1] && filterColor[2] == color[2] && filterColor[3] == color[3];
19 | }
20 |
21 | function examineDocTree(isTab, id) {
22 | let doc = documents.find(d => d.id === id);
23 | if (doc.rawPaths) {
24 | jobs.push((cb) => {
25 | if (isTab) {
26 | tabGeometry = union(tabGeometry, rawPathsToClipperPaths(doc.rawPaths, doc.transform2d));
27 | } else if (matchColor(op.filterFillColor, doc.fillColor) && matchColor(op.filterStrokeColor, doc.strokeColor)) {
28 | filteredDocIds.add(doc.id);
29 | if (!op.type.includes('Raster')) {
30 | let isClosed = false;
31 | for (let rawPath of doc.rawPaths)
32 | if (rawPath.length >= 4 && rawPath[0] == rawPath[rawPath.length - 2] && rawPath[1] == rawPath[rawPath.length - 1])
33 | isClosed = true;
34 | let clipperPaths = rawPathsToClipperPaths(doc.rawPaths, doc.transform2d);
35 | if (isClosed)
36 | geometry = xor(geometry, clipperPaths);
37 | else if (!op.filterFillColor)
38 | openGeometry = openGeometry.concat(clipperPaths);
39 | }
40 | }
41 | cb()
42 | })
43 | }
44 | if (doc.type === 'image' && !isTab) {
45 | filteredDocIds.add(doc.id);
46 | docsWithImages.push(doc)
47 | }
48 | for (let child of doc.children)
49 | examineDocTree(isTab, child);
50 | }
51 | for (let id of op.documents)
52 | examineDocTree(false, id);
53 | for (let id of op.tabDocuments)
54 | examineDocTree(true, id);
55 |
56 | let chunk = 100 / jobs.length;
57 | var percent = 0;
58 |
59 | while (jobs.length) {
60 | try {
61 | let job = jobs.shift()
62 | if (job) job(() => {
63 | percent = percent + chunk
64 | postMessage({ event: "onProgress", percent: parseInt(percent) })
65 | });
66 | } catch (error) {
67 | console.error(error)
68 | postMessage({ event: "onError", message: "Something wrong has happened, sorry.", level: "error", error: error.toString() })
69 | }
70 | }
71 |
72 | postMessage({ event: "onDone", settings, opIndex, op, geometry, openGeometry, tabGeometry, filteredDocIds, docsWithImages })
73 | self.close();
74 | }
--------------------------------------------------------------------------------
/src/lib/workers/cam-raster.js:
--------------------------------------------------------------------------------
1 | import { RasterToGcode } from '../lw.raster2gcode/raster-to-gcode.js'
2 |
3 | // On messsage received
4 | self.onmessage = function (event) {
5 | if (event.data.cmd === 'start') {
6 | start(event.data);
7 | }
8 | }
9 |
10 |
11 |
12 | // Start job
13 | function start(data) {
14 |
15 | // Create RasterToGcode object
16 | var rasterToGcode = new RasterToGcode(data.settings);
17 | Object.assign( rasterToGcode, data.properties );
18 | // Register events callbacks
19 | rasterToGcode.on('progress', function (event) {
20 | self.postMessage({ event: 'onProgress', ...event });
21 | }).on('done', function (event) {
22 | self.postMessage({ event: 'onDone', ...event });
23 | }).on('abort', function () {
24 | self.postMessage({ event: 'onAbort' });
25 | });
26 |
27 |
28 | self.postMessage({ event: 'start' });
29 | rasterToGcode.run();
30 |
31 | }
--------------------------------------------------------------------------------
/src/lib/workers/cam-wire.js:
--------------------------------------------------------------------------------
1 | import { getWireGcodeFromOp } from '../cam-gcode-wire'
2 |
3 | onmessage = (event) => {
4 |
5 | const {settings, opIndex, op, geometry=[], openGeometry=[], tabGeometry=[]} = event.data
6 | const errors = [];
7 |
8 | const showAlert = (message, level) => {
9 | errors.push({ message, level })
10 | };
11 | const progress = () => {
12 | postMessage(JSON.stringify({ event: "onProgress", gcode, errors }))
13 | };
14 | const done = (gcode) => {
15 | if (gcode === false && errors.length) {
16 | postMessage(JSON.stringify({ event: "onError", errors }))
17 | } else {
18 | postMessage(JSON.stringify({ event: "onDone", gcode }))
19 | }
20 | };
21 |
22 | getWireGcodeFromOp.apply(this, [settings, opIndex, op, geometry, openGeometry, tabGeometry, showAlert, done, progress])
23 |
24 | }
--------------------------------------------------------------------------------
/src/reducers/camera.js:
--------------------------------------------------------------------------------
1 | import { objectNoId } from '../reducers/object'
2 |
3 | export const camera = objectNoId('camera', resetCamera(null, { machineWidth: 300, machineHeight: 300 }));
4 |
5 | export function resetCamera(camera, settings) {
6 | return {
7 | eye: [settings.machineWidth / 2, settings.machineHeight / 2, Math.max(settings.machineWidth, settings.machineHeight)],
8 | center: [settings.machineWidth / 2, settings.machineHeight / 2, 0],
9 | up: [0, 1, 0],
10 | fovy: Math.PI / 2.6,
11 | showPerspective: false,
12 | };
13 | }
14 |
15 | export function zoomArea(camera, settings, workspace, { x1, y1, x2, y2 }) {
16 | let d = 300;
17 | let cx = (x1 + x2) / 2 - settings.machineBottomLeftX + workspace.workOffsetX;
18 | let cy = (y1 + y2) / 2 - settings.machineBottomLeftY + workspace.workOffsetY;
19 | let fovy = 2 * Math.atan2(Math.max(Math.abs(y2 - y1), Math.abs(x2 - x1) * workspace.height / workspace.width) / 2, d);
20 | return {
21 | eye: [cx, cy, d],
22 | center: [cx, cy, 0],
23 | up: [0, 1, 0],
24 | fovy,
25 | showPerspective: false,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/reducers/com.js:
--------------------------------------------------------------------------------
1 | import { objectNoId } from '../reducers/object'
2 |
3 | export const COM_INITIALSTATE = {
4 | serverConnected: false,
5 | machineConnected: false,
6 | playing: false,
7 | paused:false,
8 | firmware: '',
9 | firmwareVersion: '',
10 |
11 | comInterfaces:[],
12 | comPorts:[]
13 | }
14 |
15 | export function com(state = COM_INITIALSTATE, action) {
16 | state = objectNoId('com', COM_INITIALSTATE)(state, action);
17 | return state;
18 | }
19 |
--------------------------------------------------------------------------------
/src/reducers/gcode.js:
--------------------------------------------------------------------------------
1 |
2 | export const GCODE_INITIALSTATE = {
3 | gcoding: { enable: false, percent: 0},
4 | content: '',
5 | dirty:false,
6 | }
7 |
8 | export function gcode(state = GCODE_INITIALSTATE, action) {
9 |
10 | if (action.type.match(/^(DOCUMENT|OPERATION)_/gi)) {
11 | if (action.type=='DOCUMENT_SET_ATTRS'){
12 | if (!action.payload.attrs.hasOwnProperty('visible') && !action.payload.attrs.hasOwnProperty('selected'))
13 | return Object.assign(state, {dirty: true })
14 | }
15 | if (action.type=='OPERATION_SET_ATTRS'){
16 | if (!action.payload.attrs.hasOwnProperty('expanded') && !action.payload.attrs.hasOwnProperty('_docs_visible')){
17 | return Object.assign(state, {dirty: true })
18 | }
19 | }
20 | }
21 | if (action.type === 'GCODE_SET')
22 | return { ...state, dirty: false , content: action.payload };
23 | else if (action.type === 'GCODE_GENERATION')
24 | return { ...state, gcoding: action.payload }
25 | else if (action.type== 'WORKSPACE_RESET')
26 | return { ...state, dirty:false, content:''}
27 | else
28 | return state;
29 | }
30 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { undoCombineReducers, shouldSaveUndo } from './undo'
2 |
3 | import { camera, zoomArea } from './camera'
4 | import { documents, documentsLoad } from './document'
5 | import { gcode } from './gcode'
6 | import { operations, currentOperation, operationsAddDocuments, fixupOperations } from './operation'
7 | import panes from './panes'
8 | import { settings } from './settings'
9 | import { splitters } from './splitters'
10 | import { workspace } from './workspace'
11 |
12 | import { machineProfiles } from './machine-profiles'
13 | import { materialDatabase } from './material-database'
14 | import { com } from './com'
15 |
16 | import omit from 'object.omit';
17 | import { deepMerge } from '../lib/helpers'
18 |
19 | const combined = undoCombineReducers({ camera, documents, operations, currentOperation, gcode, panes, settings, splitters, workspace, machineProfiles, materialDatabase, com }, {}, shouldSaveUndo);
20 |
21 | export default function reducer(state, action) {
22 | switch (action.type) {
23 | case 'CAMERA_ZOOM_AREA':
24 | return { ...state, camera: zoomArea(state.camera, state.settings, state.workspace, action) };
25 | case 'DOCUMENT_REMOVE':
26 | case "DOCUMENT_REMOVE_SELECTED":
27 | state = combined(state, action);
28 | return { ...state, operations: fixupOperations(state.operations, state.documents) };
29 | case 'DOCUMENT_LOAD':
30 | return { ...state, documents: documentsLoad(state.documents, state.settings, action) };
31 | case 'OPERATION_ADD_DOCUMENTS':
32 | state = combined(state, action);
33 | return { ...state, operations: operationsAddDocuments(state.operations, state.documents, action) };
34 | case "SNAPSHOT_UPLOAD":
35 | let newState = omit(action.payload.snapshot, ["history"]);
36 | newState = Object.assign(newState, { gcode: { ...state.gcode, dirty: true } });
37 | newState = Object.assign({}, state, deepMerge(action.getState(), newState));
38 | return reducer(newState, { type: 'LOADED', payload: newState });
39 | default:
40 | return combined(state, action);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/reducers/machine-profiles.js:
--------------------------------------------------------------------------------
1 |
2 | import omit from 'object.omit'
3 | import {actionTypes} from 'redux-localstorage'
4 |
5 | export const MACHINEPROFILES_INITIALSTATE=((ctx)=>{
6 | let keys = ctx.keys();
7 | let values = keys.map(ctx);
8 | return (Object.assign.apply(null,[{},...values]))
9 | })(require.context('../data/lw.machines/machines', true, /\.json$/gi))
10 |
11 |
12 | export const machineProfiles = (state = MACHINEPROFILES_INITIALSTATE, action, lock=/^\*/gi) => {
13 | switch (action.type) {
14 | case "MACHINEPROFILES_ADD":
15 | if (!lock.exec(action.payload.id))
16 | return Object.assign({}, state, {[action.payload.id]: action.payload.machine});
17 | return state;
18 |
19 | case "MACHINEPROFILES_REMOVE":
20 | let item = state[action.payload.id]
21 | if (!item || item._locked) return state;
22 | return omit(state, action.payload.id);
23 |
24 | case "MACHINEPROFILES_LOAD":
25 | let allowed=omit(action.payload.machines,(val,key) => { return !key.match(lock)});
26 | return Object.assign({}, state, allowed);
27 |
28 | case actionTypes.INIT:
29 | if (action.payload) {
30 | let lockedState = {}
31 | Object.entries(MACHINEPROFILES_INITIALSTATE).forEach((vendor) => { let [key,value] = vendor; lockedState[key] = { ...value, _locked: true } });
32 | return Object.assign(action.payload.machineProfiles, lockedState);
33 | }
34 | return state;
35 |
36 | default:
37 | return state;
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/src/reducers/macros.js:
--------------------------------------------------------------------------------
1 | import { objectNoId } from '../reducers/object'
2 | import omit from 'object.omit'
3 |
4 | import Validator from 'validatorjs';
5 | import { actionTypes } from 'redux-localstorage'
6 |
7 | export const MACROS_INITIALSTATE = require("../data/macros.json");
8 |
9 | export const MACRO_VALIDATION_RULES = {
10 | label: 'required',
11 | gcode: 'required'
12 | }
13 |
14 | export const macros = (state = MACROS_INITIALSTATE, action) => {
15 | switch (action.type) {
16 | case "MACROS_RESET":
17 | return MACROS_INITIALSTATE;
18 |
19 | case "MACROS_SET_ATTRS":
20 | return Object.assign({}, state, action.payload.attrs);
21 |
22 | case "MACROS_REMOVE":
23 | return omit(state, action.payload);
24 |
25 | // both receives full redux state;
26 | case "LOADED":
27 | case actionTypes.INIT:
28 | if (action.payload) {
29 | return Object.assign(action.payload.macros || action.payload.settings.macros) //recover legacy macros data
30 | }
31 | return state;
32 |
33 | default:
34 | return state;
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/src/reducers/panes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Panes reducer.
3 | * @module
4 | */
5 |
6 | // React
7 | import React from 'react'
8 |
9 | // Actions
10 | import * as panesActions from '../actions/panes'
11 |
12 | export const PANES_INITIALSTATE='cam'
13 |
14 |
15 | /**
16 | * Handle visible state.
17 | * @function
18 | * @protected
19 | * @param {Array} panes The current panes collection.
20 | * @param {module:lib/redux-action~Action} action The action to execute.
21 | * @return {Array} The new panes collection.
22 | */
23 | function handleVisible(state = {}, action) {
24 | let visible = state.visible !== undefined ? state.visible : true
25 |
26 | switch (action.type) {
27 | case panesActions.selectPane.TYPE:
28 | return !visible || action.payload.id !== state.selected;
29 | default:
30 | return visible
31 | }
32 | }
33 |
34 | function handleSelected(state = PANES_INITIALSTATE, action) {
35 | switch (action.type) {
36 | case panesActions.selectPane.TYPE:
37 | return action.payload.id;
38 | default:
39 | return state;
40 | }
41 | }
42 |
43 | /**
44 | * Handle dock state.
45 | * @function
46 | * @param {Object} state The current state.
47 | * @param {module:lib/redux-action~Action} action The action to execute.
48 | * @return {Array} The new state.
49 | */
50 | function panes(state = {}, action) {
51 | return {
52 | visible: handleVisible(state, action),
53 | selected: handleSelected(state.selected, action),
54 | }
55 | }
56 |
57 | // Exports
58 | export default panes
59 |
--------------------------------------------------------------------------------
/src/reducers/settings.js:
--------------------------------------------------------------------------------
1 | import { objectNoId } from '../reducers/object'
2 | import Validator from 'validatorjs';
3 | import { GlobalStore } from '../index';
4 | import { actionTypes } from 'redux-localstorage'
5 | import { macros, MACROS_INITIALSTATE } from './macros'
6 |
7 | export const version = require("../../package.json").version;
8 |
9 | export const SETTINGS_VALIDATION_RULES = {
10 | machineWidth: 'numeric|min:100',
11 | machineHeight: 'numeric|min:100',
12 |
13 | gcodeLaserIntensity: 'required',
14 | gcodeSMinValue: 'required|numeric',
15 | gcodeSMaxValue: 'required|numeric',
16 | gcodeMoveUnits: 'in:mm/s,mm/min',
17 | gcodeToolTestPower: 'required|numeric|min:0|max:100',
18 | gcodeToolTestDuration: 'required|numeric|min:0',
19 | gcodeConcurrency: 'required|numeric|min:1|max:5',
20 | gcodeCurvePrecision: 'required|numeric|min:0.1|max:2',
21 |
22 | machineZEnabled: 'boolean',
23 | machineBlowerEnabled: 'boolean',
24 | machineZToolOffset: 'numeric',
25 |
26 | machineAEnabled: 'boolean',
27 |
28 | toolGridWidth: 'numeric|min:100',
29 | toolGridHeight: 'numeric|min:100',
30 | toolImagePosition: 'in:TL,TR,C,BL,BR',
31 |
32 | toolGridMinorSpacing: 'numeric|min:0.1',
33 | toolGridMajorSpacing: 'numeric|min:1',
34 |
35 | jogFeedXY: 'numeric|min:0',
36 | jogFeedZ: 'numeric|min:0',
37 |
38 | }
39 |
40 |
41 | export function ValidateSettings(bool = true, rules = SETTINGS_VALIDATION_RULES, settings = null) {
42 |
43 | if (!settings)
44 | settings = Object.assign({}, GlobalStore().getState().settings)
45 |
46 | let check = new Validator(settings, rules);
47 |
48 | if (bool)
49 | return check.passes();
50 |
51 | return check;
52 | }
53 |
54 | export const SETTINGS_INITIALSTATE = {
55 |
56 | __version: version,
57 | __selectedProfile: null,
58 | __latestRelease: null,
59 |
60 | showMachine: false,
61 | machineWidth: 300,
62 | machineHeight: 200,
63 | machineBeamDiameter: 0.2,
64 | machineBottomLeftX: 0,
65 | machineBottomLeftY: 0,
66 |
67 | machineFeedRange: {
68 | XY: {min: 1, max:50000},
69 | Z: {min: 1, max:50000},
70 | A: {min: 1, max:50000},
71 | S: {min: 0, max:30000},
72 | },
73 |
74 | machineXYProbeOffset: 0,
75 |
76 | machineZEnabled: false,
77 | machineZMatThickness: 0,
78 | machineZToolOffset: 0,
79 | machineZStartHeight: '',
80 | machineZProbeOffset: 0,
81 |
82 | machineAEnabled: false,
83 |
84 | machineBlowerEnabled: false,
85 | machineBlowerGcodeOn: '',
86 | machineBlowerGcodeOff: '',
87 |
88 | pxPerInch: 96,
89 | forcePxPerInch: false,
90 | dpiBitmap: 300,
91 |
92 |
93 | toolGridWidth: 500,
94 | toolGridHeight: 500,
95 | toolGridMinorSpacing: 10,
96 | toolGridMajorSpacing: 50,
97 | toolSafetyLockDisabled: true,
98 | toolCncMode: false,
99 | toolImagePosition: "BL",
100 | toolUseNumpad: false,
101 | toolDisplayCache: false,
102 | toolUseGamepad: false,
103 | toolCreateEmptyOps: false,
104 |
105 | toolVideoDevice: null,
106 | toolVideoPerspective: { enabled: false },
107 | toolVideoLens: { a: 1, b: 1, F: 1, scale: 1 },
108 | toolVideoFov: { x: 1, y: 1 },
109 | toolVideoResolution: "720p(HD)",
110 |
111 | toolVideoOMR: false,
112 | toolVideoOMROffsetX: 0,
113 | toolVideoOMROffsetY: 0,
114 | toolVideoOMRMarkerSize: 20,
115 |
116 | toolWebcamUrl: "",
117 | toolFeedUnits: 'mm/min',
118 | toolTestSValue: 1,
119 | toolTestDuration: 0,
120 |
121 | gcodeStart: "G21 ; Set units to mm\r\nG90 ; Absolute positioning\r\n",
122 | gcodeEnd: "M5 ; Switch tool offEnd\r\n",
123 | gcodeHoming: "",
124 | gcodeGenerator: "default",
125 | gcodeToolOn: "",
126 | gcodeToolOff: "",
127 | gcodeLaserIntensity: 'S',
128 | gcodeLaserIntensitySeparateLine: false,
129 | gcodeSMinValue: 0,
130 | gcodeSMaxValue: 1,
131 | gcodeCheckSizePower: 0,
132 | gcodeToolTestPower: 0,
133 | gcodeToolTestDuration: 0,
134 | gcodeConcurrency: 2,
135 | gcodeCurvePrecision: 0.1,
136 |
137 | comServerVersion: 'not connected',
138 | comServerIP: 'localhost:8000',
139 | comServerConnect: false,
140 | comInterfaces: [],
141 | comPorts: [],
142 | comAccumulatedJobTime: 0,
143 |
144 | connectVia: '',
145 | connectPort: '',
146 | connectBaud: '115200',
147 | connectIP: '',
148 |
149 | jogStepsize: 1,
150 | jogFeedXY: 1800,
151 | jogFeedZ: 300,
152 |
153 | macros: MACROS_INITIALSTATE,
154 |
155 | uiFcDrag: null,
156 | }
157 |
158 | export const settings = (state, action) => {
159 | state = objectNoId('settings', SETTINGS_INITIALSTATE)(state, action);
160 | Object.assign(state, { macros: macros(state.macros||{}, action)});
161 | switch (action.type) {
162 | case actionTypes.INIT:
163 | state = Object.assign({}, state, { __version: version })
164 | break;
165 | }
166 | return state;
167 | }
168 |
--------------------------------------------------------------------------------
/src/reducers/splitters.js:
--------------------------------------------------------------------------------
1 | export function splitters(state = {}, action) {
2 | switch (action.type) {
3 | case 'SPLITTER_SET_SIZE':
4 | return { ...state, [action.payload.id]: action.payload.size };
5 | default:
6 | return state;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/reducers/undo.js:
--------------------------------------------------------------------------------
1 |
2 | export function undoCombineReducers(reducers,
3 | initialState={},
4 | shouldSaveUndo= (action)=>{return !['@@INIT', 'REDUX_STORAGE_SAVE', 'REDUX_STORAGE_LOAD', 'UNDO'].includes(action.type);},
5 | undoStateKey='history'
6 | ){
7 |
8 | return (state = {}, action) => {
9 | if (action.type == "UNDO" && state[undoStateKey].length > 0){
10 | // Load previous state and pop the history
11 | return {
12 | ...Object.keys(reducers).reduce((stateKeys, key) => {
13 | stateKeys[key] = state[undoStateKey][0][key];
14 | return stateKeys || initialState;
15 | }, {}),
16 | [undoStateKey]: state[undoStateKey].slice(1)
17 | }
18 | } else {
19 | // Save a new undo unless the action is blacklisted
20 | const newHistory = shouldSaveUndo(action) ?
21 | [{
22 | ...Object.keys(reducers).reduce((stateKeys, key) => {
23 | stateKeys[key] = state[key];
24 | return stateKeys;
25 | }, {})
26 | }] : undefined;
27 |
28 | return {
29 | // Calculate the next state
30 | ...Object.keys(reducers).reduce((stateKeys, key) => {
31 | stateKeys[key] = reducers[key](state[key], action);
32 | return stateKeys;
33 | }, {}),
34 | [undoStateKey]: [
35 | ...(newHistory || []),
36 | ...(state[undoStateKey] || [])
37 | ].slice(0, 10)
38 | };
39 | }
40 | };
41 | }
42 |
43 | var LAST_ACTION = {};
44 | var LAST_ACTION_TIMEOUT = null;
45 | const LAST_ACTION_TTL = 2000;
46 |
47 | const BLACKLIST = [/^(@@|redux)/gi, 'REDUX_STORAGE_SAVE', 'REDUX_STORAGE_LOAD', 'UNDO', 'LOADED', /^SPLITTER|^MATERIALDB_|^SELECT_PANE|^GCODE_|^COM/gi];
48 |
49 |
50 | export const shouldSaveUndo = (action) => {
51 |
52 | //Last action TTL
53 | if (LAST_ACTION_TIMEOUT)
54 | clearTimeout(LAST_ACTION_TIMEOUT)
55 |
56 | for (let item of BLACKLIST) {
57 | if (action.type.search(item) >= 0) {
58 | LAST_ACTION = action;
59 | return false;
60 | }
61 | }
62 |
63 | if (action.type === LAST_ACTION.type) {
64 | if (action.type.match(/_SET_ATTRS/gi)) {
65 | let cSig = Object.keys(action.payload.attrs).sort().join(',');
66 | let lSig = Object.keys(LAST_ACTION.payload.attrs).sort().join(',');
67 | if (cSig === lSig) {
68 | LAST_ACTION_TIMEOUT = setTimeout(() => { LAST_ACTION = {} }, LAST_ACTION_TTL)
69 | return false;
70 | }
71 | }
72 |
73 | if (action.type.match(/DOCUMENT_TRANSLATE_SELECTED/gi)) {
74 | let cSig = Object.keys(action.payload).sort().join(',');
75 | let lSig = Object.keys(LAST_ACTION.payload).sort().join(',');
76 | if (cSig === lSig) {
77 | LAST_ACTION_TIMEOUT = setTimeout(() => { LAST_ACTION = {} }, LAST_ACTION_TTL)
78 | return false;
79 | }
80 | }
81 |
82 | }
83 |
84 | LAST_ACTION = action;
85 |
86 | return true
87 | };
--------------------------------------------------------------------------------
/src/reducers/workspace.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { objectNoId } from '../reducers/object'
4 |
5 | export const WORKSPACE_INITIALSTATE = {
6 | width: 1000,
7 | height: 1000,
8 | g0Rate: 1000,
9 | rotaryDiameter: 10,
10 | simTime: 1e10,
11 | cursorPos: [0, 0, 0],
12 | showGcode: true,
13 | showLaser: true,
14 | showDocuments: true,
15 | showRotary: false,
16 | showCursor: true,
17 | showWebcam: false,
18 | showRasterPreview: false,
19 | workOffsetX: 0,
20 | workOffsetY: 0,
21 | initialZoom: false,
22 | }
23 |
24 | export const workspace = objectNoId('workspace', WORKSPACE_INITIALSTATE);
25 |
--------------------------------------------------------------------------------
/src/styles/context-menu.css:
--------------------------------------------------------------------------------
1 | .react-contextmenu {
2 | min-width: 160px;
3 | padding: 5px 0;
4 | margin: 2px 0 0;
5 | font-size: 16px;
6 | color: #fff;
7 | text-align: left;
8 | background-color: #373a3c;
9 | background-clip: padding-box;
10 | border: 1px solid rgba(244, 244, 244, 0.945);
11 | border-radius: .25rem;
12 | outline: none;
13 | opacity: 0;
14 | pointer-events: none;
15 | }
16 |
17 | .react-contextmenu.react-contextmenu--visible {
18 | opacity: 1;
19 | pointer-events: auto;
20 | z-index: 10000
21 | }
22 |
23 | .react-contextmenu-item {
24 | padding: 3px 20px;
25 | font-weight: 400;
26 | line-height: 1.5;
27 | /* color: #373a3c; */
28 | color: #fff;
29 | text-align: inherit;
30 | white-space: nowrap;
31 | background: 0 0;
32 | border: 0;
33 | cursor: pointer;
34 | }
35 |
36 | .react-contextmenu-item.react-contextmenu-item--active,
37 | .react-contextmenu-item.react-contextmenu-item--selected {
38 | color: #fff;
39 | background-color: #20a0ff;
40 | border-color: #20a0ff;
41 | text-decoration: none;
42 | }
43 |
44 | .react-contextmenu-item.react-contextmenu-item--disabled,
45 | .react-contextmenu-item.react-contextmenu-item--disabled:hover {
46 | color: #878a8c;
47 | background-color: transparent;
48 | border-color: rgba(0,0,0,.15);
49 | }
50 |
51 | .react-contextmenu-item--divider {
52 | margin-bottom: 3px;
53 | padding: 2px 0;
54 | border-bottom: 1px solid rgba(0,0,0,.15);
55 | cursor: inherit;
56 | }
57 | .react-contextmenu-item--divider:hover {
58 | background-color: transparent;
59 | border-color: rgba(0,0,0,.15);
60 | }
61 |
62 | .react-contextmenu-item.react-contextmenu-submenu {
63 | padding: 0;
64 | }
65 |
66 | .react-contextmenu-item.react-contextmenu-submenu > .react-contextmenu-item {
67 | }
68 |
69 | .react-contextmenu-item.react-contextmenu-submenu > .react-contextmenu-item:after {
70 | content: "▶";
71 | display: inline-block;
72 | position: absolute;
73 | right: 7px;
74 | }
75 |
76 | .example-multiple-targets::after {
77 | content: attr(data-count);
78 | display: block;
79 | }
80 |
--------------------------------------------------------------------------------
/src/styles/forms.css:
--------------------------------------------------------------------------------
1 | .quadrantField {float:right}
2 | .quadrantField .bkg { fill:#4C4D4D; }
3 | .quadrantField circle {fill: white}
4 | .quadrantField .area:not(.disabled):hover circle {fill: #cFd}
5 |
6 | .quadrantField path {fill:black}
7 | .quadrantField .area.disabled {opacity: 0.2}
8 | .quadrantField .area.active circle {fill: #0e3}
9 |
10 | .checkboxListField { max-height: 400px; overflow-y:auto; overflow-x:hidden; margin-bottom: 0.5em; border: 1px solid #eee; border-radius: 5px; padding: 0.5em }
11 |
12 | .Select-menu-outer {z-index: 1000}
13 |
14 | .toggleField .react-toggle {float:right}
15 | .toggleField label {text-transform: uppercase; font-size: smaller}
--------------------------------------------------------------------------------
/src/styles/material-database.css:
--------------------------------------------------------------------------------
1 |
2 | /*FullSizeModal*/
3 |
4 | .full-width {width: 100%}
5 |
6 | .full-width .modal-dialog {
7 | width: 98%;
8 | max-height: 92%;
9 | padding: 0;
10 | }
11 |
12 | .full-width .modal-content {
13 | max-height: 99%;
14 | }
15 |
16 |
17 |
18 | .materialPicker small {color: #666; flex-grow: 2; text-align: right}
19 |
20 | .details {margin-top: 2px; margin-left: 10px}
21 | .details .handler {display:flex; flex-direction: row; align-items: center; flex-grow:2}
22 | .details .handler > * {flex-grow:1}
23 | .details heading button {margin-left: 5px}
24 | .details heading {display:flex;margin:0}
25 | .details heading .summary { display:flex; flex-grow:1}
26 | .details heading .summary small {margin-left: 1em}
27 |
28 | .details heading .summary > * {margin-top:0}
29 | .details:hover heading {background: rgba(0, 126, 255, 0.08); border-radius: 5px}
30 |
31 | .materialPicker > section > heading {display:flex; flex-direction: row; align-items: center; border-bottom: 1px solid #eee; }
32 | .materialPicker table {font-size: 0.8em; margin-left: 1.2em; width: 98%; margin-top:0.5em}
33 | .materialPicker table td,
34 | .materialPicker table th {padding: 2px !important}
35 | .materialPicker table td {text-align: right}
36 |
37 | .nestedTableWrapper {margin-Left: 10px; padding-left:3px; border-Left: 3px solid #ccc; border-top: 1px solid #f6f6f6}
38 |
39 |
40 | #groupsPane {min-width: 200px}
41 | #groupsPane heading {display:block; border: 1px solid #eee; padding: 2px; margin-bottom: 1px; border-radius: 5px}
42 | #groupsPane heading:hover {background: #f6f6f6}
43 | #groupsPane heading > * {display:block}
44 | #groupsPane heading h5 {margin-top: 0}
45 | #groupsPane heading small { margin: 0 0 5px 5px}
46 | #groupsPane heading.active {background: rgba(0, 126, 255, 0.08); border: 1px solid rgba(0, 126, 255, 0.24)}
47 | #groupsPane .full-height {position: relative}
48 | #groupsPane .listing {overflow-y: auto; flex-grow:10 }
49 |
50 | .paneToolbar { width: 100%; background: #eee; padding: 2px; border-radius: 5px; text-align: right; margin-bottom: 5px; }
51 | .paneToolbar .btn {margin-right: 2px}
52 | .paneToolbar h5 {float:left; margin:0}
53 |
54 | @media only screen and (min-height: 600px) {
55 | .paneSizer {height:400px}
56 | }
57 | @media only screen and (min-height: 800px) {
58 | .paneSizer {height:600px}
59 | }
60 | @media only screen and (min-height: 1000px) {
61 | .paneSizer {height:800px}
62 | }
63 |
64 | #operationsPane .operationHeading {border-bottom: 1px solid #eee; margin-bottom: 5px; display:block; padding-right: 5px; overflow-y:auto; flex-grow:10 }
65 | #operationsPane .details.template {
66 | background-color: #f6f6f6; margin: 2px; padding: 2px 2px 2px 10px; border-radius: 5px
67 | }
68 |
69 | #operationsPane .details.editable heading {
70 | background-color: #fffaf0;
71 | }
72 |
73 | #operationsPane .details {margin-bottom: 2px}
74 |
75 | #operationsPane .has-error > input {border: 1px red solid}
76 | #operationsPane .has-error:after{content:attr(title); color: red; margin-left: 1em}
77 |
78 | .paneContainer { margin-top: 10px; padding: 2px; border: 1px solid #eee; border-radius: 5px}
79 |
80 | #operationsPane, #groupsPane {
81 | overflow: hidden;
82 | }
83 |
84 | #groupsPane {
85 | flex-grow: 1;
86 | min-width: 60px;
87 | display: flex;
88 | }
89 |
90 |
91 | #operationsPane {
92 | display: flex;
93 | flex-direction: row;
94 | width: 100%;
95 | align-items: top;
96 | }
97 |
98 | #operationsPane .left, #operationsPane .right {flex-grow:1; overflow-y:auto;margin: 2px}
99 |
100 | .innerPane { flex-direction: column; display:flex}
101 |
102 | #operationsPane caption {padding-left: 5px; text-transform: uppercase; font-size: smaller; font-weight: bold; color: #000;background: rgba(0, 126, 255, 0.08);}
103 |
104 | #operationsPane table tr > * {font-size:smaller}
105 |
106 | #operationsPane fieldset legend {color: #007eff}
--------------------------------------------------------------------------------
/src/styles/resizer.css:
--------------------------------------------------------------------------------
1 |
2 | .Resizer {
3 | background: #000;
4 | opacity: .2;
5 | z-index: 1;
6 | -moz-box-sizing: border-box;
7 | -webkit-box-sizing: border-box;
8 | box-sizing: border-box;
9 | -moz-background-clip: padding;
10 | -webkit-background-clip: padding;
11 | background-clip: padding-box;
12 | }
13 |
14 | .Resizer:hover {
15 | -webkit-transition: all 2s ease;
16 | transition: all 2s ease;
17 | }
18 |
19 | .Resizer.horizontal {
20 | height: 11px;
21 | margin: -5px 0;
22 | border-top: 5px solid rgba(255, 255, 255, 0);
23 | border-bottom: 5px solid rgba(255, 255, 255, 0);
24 | cursor: row-resize;
25 | width: 100%;
26 | }
27 |
28 | .Resizer.horizontal:hover {
29 | border-top: 5px solid rgba(0, 0, 0, 0.5);
30 | border-bottom: 5px solid rgba(0, 0, 0, 0.5);
31 | }
32 |
33 | .Resizer.vertical {
34 | width: 11px;
35 | margin: 0 -5px;
36 | border-left: 5px solid rgba(255, 255, 255, 0);
37 | border-right: 5px solid rgba(255, 255, 255, 0);
38 | cursor: col-resize;
39 | height: 100%;
40 | }
41 |
42 | .Resizer.vertical:hover {
43 | border-left: 5px solid rgba(0, 0, 0, 0.5);
44 | border-right: 5px solid rgba(0, 0, 0, 0.5);
45 | }
46 | Resizer.disabled {
47 | cursor: not-allowed;
48 | }
49 | Resizer.disabled:hover {
50 | border-color: transparent;
51 | }
52 |
--------------------------------------------------------------------------------
/src/styles/webcam.css:
--------------------------------------------------------------------------------
1 | .webcamViewport {border: 1px solid #eee; position:relative; width: 100%; height:100%; overflow:hidden}
2 | .webcamViewport img[src="#"] {display:none}
3 | .webcamViewport video {display:none}
4 |
5 | .perspectiveWebcam .viewPort { position:relative; overflow:hidden;}
6 |
7 | .coordinator {pointer-events: none}
8 | .coordinator .symbol {pointer-events: all}
9 |
10 | .videoControls table input[type=number]{width: 4em}
11 |
12 |
--------------------------------------------------------------------------------
/up_src_to_dist.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -f "dist/index.html" ]; then
4 | echo "Found dist/index.html"
5 | echo "Removing dist/index.html"
6 | rm dist/index.html
7 | echo "Copying src/index.html to dist/index.html"
8 | cp src/index.html dist/index.html
9 | else
10 | echo "dist/index.html not found"
11 | echo "Copying src/index.html to dist/index.html"
12 | cp src/index.html dist/index.html
13 | fi
14 |
15 | echo "Done"
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 |
4 | var src_path = path.resolve('./src');
5 | var dist_path = path.resolve('./dist');
6 |
7 | module.exports = {
8 | context: src_path,
9 | entry: [
10 | 'webpack-dev-server/client?http://0.0.0.0:8080', 'webpack/hot/only-dev-server', 'babel-polyfill', './index.js'
11 | ],
12 | output: {
13 | path: dist_path,
14 | filename: 'index.js'
15 | },
16 | module: {
17 | loaders: [
18 | {
19 | test: /\.js$/,
20 | exclude: /node_modules/,
21 | loader: 'babel-loader',
22 | query: {
23 | presets: ['react'],
24 | plugins: ['transform-es2015-destructuring', 'transform-es2015-parameters', 'transform-object-rest-spread', 'transform-es2015-modules-commonjs', 'react-hot-loader/babel']
25 | }
26 | }, {
27 | test: /\.css$/,
28 | loader: 'style-loader!css-loader'
29 | }, {
30 | test: /\.png$/,
31 | loader: 'url-loader?limit=100000'
32 | }, {
33 | test: /\.jpg$/,
34 | loader: 'file-loader'
35 | }, {
36 | test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
37 | loader: 'url-loader?limit=10000&mimetype=application/font-woff'
38 | }, {
39 | test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
40 | loader: 'url-loader?limit=10000&mimetype=application/octet-stream'
41 | }, {
42 | test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
43 | loader: 'file-loader'
44 | }, {
45 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
46 | loader: 'url-loader?limit=10000&mimetype=image/svg+xml'
47 | }, {
48 | test: /\.json$/,
49 | loader: 'json-loader'
50 | }, {
51 | test: /\.swf$/,
52 | loader: "file-loader?name=[path][name].[ext]"
53 | }, {
54 | test: require.resolve('snapsvg'),
55 | loader: 'imports-loader?this=>window,fix=>module.exports=0'
56 | },
57 | ]
58 | },
59 | plugins: [
60 | new webpack.ProvidePlugin({$: 'jquery', jQuery: 'jquery'}),
61 | new webpack.HotModuleReplacementPlugin(),
62 | ],
63 | devServer: {
64 | contentBase: dist_path,
65 | inline: false,
66 | hot: true,
67 | host: 'localhost' // originally 0.0.0.0
68 | },
69 | devtool: 'source-map'
70 | };
71 |
--------------------------------------------------------------------------------
/win.shell.cmd:
--------------------------------------------------------------------------------
1 | :: Commands alias (shorthands)
2 | @DOSKEY install=npm install
3 | @DOSKEY start=npm start
4 | @DOSKEY bundle-dev=npm run bundle-dev
5 | @DOSKEY bundle-prod=npm run bundle-prod
6 | @DOSKEY build-docs=npm run build-docs
7 |
8 | :: Print commands reminder
9 | @ECHO.
10 | @ECHO Rack-Robotics Development Environment
11 | @ECHO -------------------------------------------------------------
12 | @ECHO npm install - Install the development environment.
13 | @ECHO npm start - Start the live development server.
14 | @ECHO npm run bundle-dev - Bundle the project for development.
15 | @ECHO npm run bundle-prod - Bundle the project for production.
16 | @ECHO npm run build-docs - Build the sources documentations.
17 | @ECHO -------------------------------------------------------------
18 | @ECHO.
19 | @ECHO OFF
20 |
21 | :: Prompt
22 | cmd /k
23 |
--------------------------------------------------------------------------------