├── .gitignore ├── .vscode └── launch.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README.zh-Hant.md ├── bin ├── controller.bat ├── etc │ ├── master.jsonnet │ ├── master │ │ ├── db.libsonnet │ │ ├── def.libsonnet │ │ ├── http.libsonnet │ │ ├── logger.libsonnet │ │ ├── session.libsonnet │ │ └── system.libsonnet │ ├── slave.jsonnet │ └── slave │ │ ├── connect.libsonnet │ │ ├── db.libsonnet │ │ ├── def.libsonnet │ │ ├── logger.libsonnet │ │ └── system.libsonnet ├── nginx_webpc.conf ├── run-linux ├── service.bat ├── shell-bash.bat ├── shell-linux ├── shell-windows.bat ├── useradd.sh ├── webpc-master.exe ├── webpc-master.service ├── webpc-master.xml ├── webpc-slave.exe ├── webpc-slave.service ├── webpc-slave.xml ├── winpty-agent.exe └── winpty.dll ├── build.sh ├── cmd ├── forward.go ├── init.go ├── internal │ ├── client │ │ ├── client.go │ │ ├── conn.go │ │ └── dialer.go │ ├── forward │ │ ├── run.go │ │ ├── socks5 │ │ │ ├── api.go │ │ │ ├── socks4.go │ │ │ └── socks5.go │ │ └── worker.go │ ├── master │ │ ├── grpc.go │ │ ├── listener.go │ │ ├── run.go │ │ ├── server.go │ │ └── system.go │ └── slave │ │ ├── grpc.go │ │ └── run.go ├── master.go ├── slave.go ├── socks5.go └── upgrade.go ├── configure ├── configure.go ├── db.go ├── http.go ├── session.go ├── slave.go └── system.go ├── db ├── const.go ├── data │ └── modtime.go └── manipulator │ ├── init.go │ └── modtime.go ├── docker ├── 1.png ├── Dockerfile ├── README.md ├── docker-entrypoint.sh └── source │ └── etc │ ├── master.jsonnet │ ├── master │ ├── db.libsonnet │ ├── def.libsonnet │ ├── http.libsonnet │ ├── logger.libsonnet │ ├── session.libsonnet │ └── system.libsonnet │ ├── slave.jsonnet │ └── slave │ ├── connect.libsonnet │ ├── db.libsonnet │ ├── def.libsonnet │ ├── logger.libsonnet │ └── system.libsonnet ├── document ├── fs.gif ├── shell.gif └── vnc.gif ├── go.mod ├── go.sum ├── logger ├── cache.go ├── init.go ├── init_console.go ├── listener.go └── logger.go ├── m ├── forward │ ├── forward.go │ └── state.go ├── helper │ ├── helper.go │ ├── http.go │ ├── http_range.go │ ├── serve_content.go │ ├── serve_message.go │ └── session.go ├── register │ ├── grpc.go │ └── http.go ├── server │ ├── group │ │ ├── auth.go │ │ ├── init.go │ │ ├── internal │ │ │ ├── db │ │ │ │ ├── data.go │ │ │ │ ├── init.go │ │ │ │ └── manipulator.go │ │ │ └── tree │ │ │ │ ├── element.go │ │ │ │ ├── init.go │ │ │ │ └── tree.go │ │ └── srv.go │ ├── logger │ │ ├── auth.go │ │ ├── init.go │ │ └── srv.go │ ├── session │ │ ├── init.go │ │ └── srv.go │ ├── slave │ │ ├── auth.go │ │ ├── init.go │ │ ├── internal │ │ │ └── db │ │ │ │ ├── data.go │ │ │ │ ├── init.go │ │ │ │ └── manipulator.go │ │ ├── srv.go │ │ └── subscription.go │ ├── system │ │ ├── auth.go │ │ ├── init.go │ │ └── srv.go │ └── user │ │ ├── auth.go │ │ ├── init.go │ │ ├── internal │ │ └── db │ │ │ ├── data.go │ │ │ ├── init.go │ │ │ └── manipulator.go │ │ └── srv.go └── web │ ├── api │ ├── api.go │ ├── forward │ │ ├── init.go │ │ └── v1 │ │ │ ├── filesystem.go │ │ │ ├── forward.go │ │ │ ├── init.go │ │ │ ├── logger.go │ │ │ ├── shell.go │ │ │ ├── static.go │ │ │ └── vnc.go │ └── v1 │ │ ├── dialer.go │ │ ├── init.go │ │ ├── internal │ │ └── dialer │ │ │ ├── conn.go │ │ │ ├── listener.go │ │ │ └── put.go │ │ ├── logger.go │ │ └── slave.go │ ├── contrib │ └── compression │ │ ├── handler.go │ │ ├── options.go │ │ └── writer.go │ ├── filesystem.go │ ├── forward.go │ ├── helper.go │ ├── host.go │ ├── session.go │ ├── types.go │ ├── view │ └── view.go │ └── websocket.go ├── main.go ├── pb └── 81dd3b50-f343-11eb-8332-dfc4915441d6 │ ├── forward │ ├── forward │ │ └── forward.proto │ ├── fs │ │ └── fs.proto │ ├── logger │ │ └── logger.proto │ ├── shell │ │ └── shell.proto │ ├── system │ │ └── system.proto │ └── vnc │ │ └── vnc.proto │ ├── group │ └── group.proto │ ├── logger │ └── logger.proto │ ├── session │ └── session.proto │ ├── slave │ └── slave.proto │ ├── system │ └── system.proto │ └── user │ └── user.proto ├── script ├── clear.sh ├── conf.sh ├── docker.sh ├── document.sh ├── go.sh ├── grpc.sh ├── pack.sh ├── pack_platform.sh ├── run.sh └── view.sh ├── sessionid ├── init.go ├── is.go ├── manager.go ├── platforms.go └── session.go ├── signal ├── group │ ├── delete.go │ ├── exists.go │ └── ids.go ├── session │ ├── password.go │ └── signin.go └── slave │ ├── code.go │ └── get.go ├── single ├── logger │ └── db │ │ ├── filename.go │ │ └── init.go ├── mount │ ├── filesystem.go │ ├── init.go │ └── mount.go └── upgrade │ ├── download.go │ ├── upgrade.go │ └── version.go ├── slave ├── grpc.go └── server │ ├── forward │ ├── auth.go │ ├── init.go │ ├── internal │ │ └── connect │ │ │ └── worker.go │ └── srv.go │ ├── fs │ ├── init.go │ ├── internal │ │ ├── compress │ │ │ ├── compressor.go │ │ │ ├── tar.go │ │ │ ├── worker.go │ │ │ └── zip.go │ │ ├── copied │ │ │ ├── dir.go │ │ │ ├── file.go │ │ │ ├── move.go │ │ │ ├── serve.go │ │ │ └── worker.go │ │ ├── open │ │ │ └── worker.go │ │ ├── uncompress │ │ │ ├── tar.go │ │ │ ├── uncompressor.go │ │ │ ├── worker.go │ │ │ └── zip.go │ │ └── upload │ │ │ ├── chunk.go │ │ │ ├── hash.go │ │ │ ├── merge.go │ │ │ └── upload.go │ └── srv.go │ ├── logger │ ├── auth.go │ ├── init.go │ └── srv.go │ ├── shell │ ├── auth.go │ ├── init.go │ ├── internal │ │ ├── connect │ │ │ ├── conn.go │ │ │ └── worker.go │ │ ├── db │ │ │ ├── data.go │ │ │ ├── init.go │ │ │ └── manipulator.go │ │ ├── shell │ │ │ ├── element.go │ │ │ ├── init.go │ │ │ ├── manager.go │ │ │ └── shell.go │ │ └── term │ │ │ ├── term_others.go │ │ │ └── term_windows.go │ └── srv.go │ ├── system │ ├── init.go │ └── srv.go │ └── vnc │ ├── auth.go │ ├── init.go │ ├── internal │ └── connect │ │ └── worker.go │ └── srv.go ├── static ├── document │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── index.html │ ├── swagger-ui-bundle.js │ ├── swagger-ui-standalone-preset.js │ └── swagger-ui.css ├── favicon.ico ├── public │ ├── 3rdpartylicenses.txt │ ├── LICENSE.txt │ ├── css │ │ └── fontawesome.min.css │ ├── noVNC │ │ ├── .eslintignore │ │ ├── .eslintrc │ │ ├── .github │ │ │ ├── ISSUE_TEMPLATE │ │ │ │ ├── bug_report.md │ │ │ │ ├── config.yml │ │ │ │ └── feature_request.md │ │ │ └── workflows │ │ │ │ ├── deploy.yml │ │ │ │ ├── lint.yml │ │ │ │ ├── test.yml │ │ │ │ └── translate.yml │ │ ├── .gitignore │ │ ├── .gitmodules │ │ ├── AUTHORS │ │ ├── LICENSE.txt │ │ ├── README.md │ │ ├── app │ │ │ ├── error-handler.js │ │ │ ├── images │ │ │ │ ├── alt.svg │ │ │ │ ├── clipboard.svg │ │ │ │ ├── connect.svg │ │ │ │ ├── ctrl.svg │ │ │ │ ├── ctrlaltdel.svg │ │ │ │ ├── disconnect.svg │ │ │ │ ├── drag.svg │ │ │ │ ├── error.svg │ │ │ │ ├── esc.svg │ │ │ │ ├── expander.svg │ │ │ │ ├── fullscreen.svg │ │ │ │ ├── handle.svg │ │ │ │ ├── handle_bg.svg │ │ │ │ ├── icons │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── novnc-icon-sm.svg │ │ │ │ │ ├── novnc-icon.svg │ │ │ │ │ ├── novnc-ios-120.png │ │ │ │ │ ├── novnc-ios-152.png │ │ │ │ │ ├── novnc-ios-167.png │ │ │ │ │ ├── novnc-ios-180.png │ │ │ │ │ ├── novnc-ios-40.png │ │ │ │ │ ├── novnc-ios-58.png │ │ │ │ │ ├── novnc-ios-60.png │ │ │ │ │ ├── novnc-ios-80.png │ │ │ │ │ ├── novnc-ios-87.png │ │ │ │ │ ├── novnc-ios-icon.svg │ │ │ │ │ └── novnc.ico │ │ │ │ ├── info.svg │ │ │ │ ├── keyboard.svg │ │ │ │ ├── power.svg │ │ │ │ ├── settings.svg │ │ │ │ ├── tab.svg │ │ │ │ ├── toggleextrakeys.svg │ │ │ │ ├── warning.svg │ │ │ │ └── windows.svg │ │ │ ├── locale │ │ │ │ ├── README │ │ │ │ ├── cs.json │ │ │ │ ├── de.json │ │ │ │ ├── el.json │ │ │ │ ├── es.json │ │ │ │ ├── fr.json │ │ │ │ ├── it.json │ │ │ │ ├── ja.json │ │ │ │ ├── ko.json │ │ │ │ ├── nl.json │ │ │ │ ├── pl.json │ │ │ │ ├── pt_BR.json │ │ │ │ ├── ru.json │ │ │ │ ├── sv.json │ │ │ │ ├── tr.json │ │ │ │ ├── zh_CN.json │ │ │ │ └── zh_TW.json │ │ │ ├── localization.js │ │ │ ├── sounds │ │ │ │ ├── CREDITS │ │ │ │ ├── bell.mp3 │ │ │ │ └── bell.oga │ │ │ ├── styles │ │ │ │ ├── Orbitron700.ttf │ │ │ │ ├── Orbitron700.woff │ │ │ │ ├── base.css │ │ │ │ └── input.css │ │ │ ├── ui.js │ │ │ └── webutil.js │ │ ├── core │ │ │ ├── base64.js │ │ │ ├── decoders │ │ │ │ ├── copyrect.js │ │ │ │ ├── hextile.js │ │ │ │ ├── jpeg.js │ │ │ │ ├── raw.js │ │ │ │ ├── rre.js │ │ │ │ ├── tight.js │ │ │ │ ├── tightpng.js │ │ │ │ └── zrle.js │ │ │ ├── deflator.js │ │ │ ├── des.js │ │ │ ├── display.js │ │ │ ├── encodings.js │ │ │ ├── inflator.js │ │ │ ├── input │ │ │ │ ├── domkeytable.js │ │ │ │ ├── fixedkeys.js │ │ │ │ ├── gesturehandler.js │ │ │ │ ├── keyboard.js │ │ │ │ ├── keysym.js │ │ │ │ ├── keysymdef.js │ │ │ │ ├── util.js │ │ │ │ ├── vkeys.js │ │ │ │ └── xtscancodes.js │ │ │ ├── ra2.js │ │ │ ├── rfb.js │ │ │ ├── util │ │ │ │ ├── browser.js │ │ │ │ ├── cursor.js │ │ │ │ ├── element.js │ │ │ │ ├── events.js │ │ │ │ ├── eventtarget.js │ │ │ │ ├── int.js │ │ │ │ ├── logging.js │ │ │ │ ├── md5.js │ │ │ │ └── strings.js │ │ │ └── websock.js │ │ ├── docs │ │ │ ├── API-internal.md │ │ │ ├── API.md │ │ │ ├── EMBEDDING.md │ │ │ ├── LIBRARY.md │ │ │ ├── LICENSE.BSD-2-Clause │ │ │ ├── LICENSE.BSD-3-Clause │ │ │ ├── LICENSE.MPL-2.0 │ │ │ ├── LICENSE.OFL-1.1 │ │ │ ├── flash_policy.txt │ │ │ ├── links │ │ │ ├── notes │ │ │ ├── novnc_proxy.1 │ │ │ ├── rfb_notes │ │ │ ├── rfbproto-3.3.pdf │ │ │ ├── rfbproto-3.7.pdf │ │ │ └── rfbproto-3.8.pdf │ │ ├── karma.conf.js │ │ ├── package.json │ │ ├── po │ │ │ ├── .eslintrc │ │ │ ├── Makefile │ │ │ ├── cs.po │ │ │ ├── de.po │ │ │ ├── el.po │ │ │ ├── es.po │ │ │ ├── fr.po │ │ │ ├── it.po │ │ │ ├── ja.po │ │ │ ├── ko.po │ │ │ ├── nl.po │ │ │ ├── noVNC.pot │ │ │ ├── pl.po │ │ │ ├── po2js │ │ │ ├── pt_BR.po │ │ │ ├── ru.po │ │ │ ├── sv.po │ │ │ ├── tr.po │ │ │ ├── xgettext-html │ │ │ ├── zh_CN.po │ │ │ └── zh_TW.po │ │ ├── snap │ │ │ ├── hooks │ │ │ │ └── configure │ │ │ ├── local │ │ │ │ └── svc_wrapper.sh │ │ │ └── snapcraft.yaml │ │ ├── tests │ │ │ ├── .eslintrc │ │ │ ├── assertions.js │ │ │ ├── fake.websocket.js │ │ │ ├── playback-ui.js │ │ │ ├── playback.js │ │ │ ├── test.base64.js │ │ │ ├── test.browser.js │ │ │ ├── test.copyrect.js │ │ │ ├── test.deflator.js │ │ │ ├── test.display.js │ │ │ ├── test.gesturehandler.js │ │ │ ├── test.helper.js │ │ │ ├── test.hextile.js │ │ │ ├── test.inflator.js │ │ │ ├── test.int.js │ │ │ ├── test.jpeg.js │ │ │ ├── test.keyboard.js │ │ │ ├── test.localization.js │ │ │ ├── test.ra2.js │ │ │ ├── test.raw.js │ │ │ ├── test.rfb.js │ │ │ ├── test.rre.js │ │ │ ├── test.tight.js │ │ │ ├── test.tightpng.js │ │ │ ├── test.util.js │ │ │ ├── test.websock.js │ │ │ ├── test.webutil.js │ │ │ ├── test.zrle.js │ │ │ └── vnc_playback.html │ │ ├── utils │ │ │ ├── .eslintrc │ │ │ ├── README.md │ │ │ ├── b64-to-binary.pl │ │ │ ├── convert.js │ │ │ ├── genkeysymdef.js │ │ │ ├── novnc_proxy │ │ │ ├── u2x11 │ │ │ └── validate │ │ ├── vendor │ │ │ └── pako │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ └── lib │ │ │ │ ├── utils │ │ │ │ └── common.js │ │ │ │ └── zlib │ │ │ │ ├── adler32.js │ │ │ │ ├── constants.js │ │ │ │ ├── crc32.js │ │ │ │ ├── deflate.js │ │ │ │ ├── gzheader.js │ │ │ │ ├── inffast.js │ │ │ │ ├── inflate.js │ │ │ │ ├── inftrees.js │ │ │ │ ├── messages.js │ │ │ │ ├── trees.js │ │ │ │ └── zstream.js │ │ ├── vnc.html │ │ └── vnc_lite.html │ ├── theme │ │ ├── color-deeppurple-amber.css │ │ ├── color-indigo-pink.css │ │ ├── color-pink-bluegrey.css │ │ ├── color-purple-green.css │ │ ├── deeppurple-amber.css │ │ ├── flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 │ │ ├── icon.css │ │ ├── indigo-pink.css │ │ ├── pink-bluegrey.css │ │ └── purple-green.css │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 └── static.go ├── third_party └── googleapis │ ├── LICENSE │ ├── README.grpc-gateway │ └── google │ ├── api │ ├── annotations.proto │ ├── field_behavior.proto │ ├── http.proto │ └── httpbody.proto │ └── rpc │ ├── code.proto │ ├── error_details.proto │ └── status.proto ├── utils ├── bytes.go ├── gateway.go ├── match.go ├── match_test.go └── path.go ├── version ├── platform.go └── version.go └── view ├── .angulardoc.json ├── .browserslistrc ├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── karma.conf.js ├── messages.xlf ├── ngsw-config.json ├── package-lock.json ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app │ │ ├── dialog │ │ │ ├── add │ │ │ │ ├── add.component.html │ │ │ │ ├── add.component.scss │ │ │ │ ├── add.component.spec.ts │ │ │ │ └── add.component.ts │ │ │ ├── code │ │ │ │ ├── code.component.html │ │ │ │ ├── code.component.scss │ │ │ │ ├── code.component.spec.ts │ │ │ │ └── code.component.ts │ │ │ ├── delete │ │ │ │ ├── delete.component.html │ │ │ │ ├── delete.component.scss │ │ │ │ ├── delete.component.spec.ts │ │ │ │ └── delete.component.ts │ │ │ ├── edit │ │ │ │ ├── edit.component.html │ │ │ │ ├── edit.component.scss │ │ │ │ ├── edit.component.spec.ts │ │ │ │ └── edit.component.ts │ │ │ └── group │ │ │ │ ├── group.component.html │ │ │ │ ├── group.component.scss │ │ │ │ ├── group.component.spec.ts │ │ │ │ └── group.component.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.spec.ts │ │ │ └── home.component.ts │ │ └── query │ │ │ ├── query.component.html │ │ │ ├── query.component.scss │ │ │ ├── query.component.spec.ts │ │ │ ├── query.component.ts │ │ │ ├── query.ts │ │ │ └── state.ts │ ├── content │ │ ├── about │ │ │ ├── about.component.html │ │ │ ├── about.component.scss │ │ │ ├── about.component.spec.ts │ │ │ └── about.component.ts │ │ ├── content-routing.module.ts │ │ ├── content.module.ts │ │ └── version │ │ │ ├── version.component.html │ │ │ ├── version.component.scss │ │ │ ├── version.component.spec.ts │ │ │ └── version.component.ts │ ├── core │ │ ├── core.module.ts │ │ ├── core │ │ │ ├── api.ts │ │ │ └── restful.ts │ │ ├── group │ │ │ ├── group.service.spec.ts │ │ │ ├── group.service.ts │ │ │ ├── keys.service.spec.ts │ │ │ ├── keys.service.ts │ │ │ └── tree.ts │ │ ├── guard │ │ │ ├── access.guard.spec.ts │ │ │ ├── access.guard.ts │ │ │ ├── fs.guard.spec.ts │ │ │ ├── fs.guard.ts │ │ │ ├── root.guard.spec.ts │ │ │ ├── root.guard.ts │ │ │ ├── shell.guard.spec.ts │ │ │ └── shell.guard.ts │ │ ├── i18n │ │ │ ├── i18n.service.spec.ts │ │ │ └── i18n.service.ts │ │ ├── interceptor │ │ │ ├── header.service.spec.ts │ │ │ ├── header.service.ts │ │ │ └── upgraded.ts │ │ ├── navigation │ │ │ ├── navigation.service.spec.ts │ │ │ └── navigation.service.ts │ │ ├── net │ │ │ └── client.ts │ │ ├── session │ │ │ ├── session.service.spec.ts │ │ │ ├── session.service.ts │ │ │ ├── session.ts │ │ │ ├── session_client.ts │ │ │ └── session_request.ts │ │ ├── settings │ │ │ ├── settings.service.spec.ts │ │ │ └── settings.service.ts │ │ ├── toaster.service.spec.ts │ │ ├── toaster.service.ts │ │ └── utils │ │ │ ├── aes-local-storage.ts │ │ │ ├── aes.ts │ │ │ ├── closed.ts │ │ │ ├── completer.ts │ │ │ ├── containers.ts │ │ │ ├── datetime.ts │ │ │ ├── loader.ts │ │ │ ├── local-storage.ts │ │ │ ├── md5.ts │ │ │ ├── promise.ts │ │ │ ├── requirenet.ts │ │ │ ├── utils.ts │ │ │ └── xterm.ts │ ├── dev │ │ ├── animations │ │ │ ├── animations.component.html │ │ │ ├── animations.component.scss │ │ │ ├── animations.component.spec.ts │ │ │ └── animations.component.ts │ │ ├── dev-routing.module.ts │ │ ├── dev.module.ts │ │ ├── index │ │ │ ├── index.component.html │ │ │ ├── index.component.scss │ │ │ ├── index.component.spec.ts │ │ │ └── index.component.ts │ │ └── toaster │ │ │ ├── toaster.component.html │ │ │ ├── toaster.component.scss │ │ │ ├── toaster.component.spec.ts │ │ │ └── toaster.component.ts │ ├── forward-fs │ │ ├── dialog │ │ │ ├── compress │ │ │ │ ├── compress.component.html │ │ │ │ ├── compress.component.scss │ │ │ │ ├── compress.component.spec.ts │ │ │ │ ├── compress.component.ts │ │ │ │ └── state.ts │ │ │ ├── copy │ │ │ │ ├── copy.component.html │ │ │ │ ├── copy.component.scss │ │ │ │ ├── copy.component.spec.ts │ │ │ │ ├── copy.component.ts │ │ │ │ └── state.ts │ │ │ ├── event.ts │ │ │ ├── exists-choice │ │ │ │ ├── exists-choice.component.html │ │ │ │ ├── exists-choice.component.scss │ │ │ │ ├── exists-choice.component.spec.ts │ │ │ │ └── exists-choice.component.ts │ │ │ ├── exists │ │ │ │ ├── exists.component.html │ │ │ │ ├── exists.component.scss │ │ │ │ ├── exists.component.spec.ts │ │ │ │ └── exists.component.ts │ │ │ ├── new-file │ │ │ │ ├── new-file.component.html │ │ │ │ ├── new-file.component.scss │ │ │ │ ├── new-file.component.spec.ts │ │ │ │ └── new-file.component.ts │ │ │ ├── new-folder │ │ │ │ ├── new-folder.component.html │ │ │ │ ├── new-folder.component.scss │ │ │ │ ├── new-folder.component.spec.ts │ │ │ │ └── new-folder.component.ts │ │ │ ├── property │ │ │ │ ├── property.component.html │ │ │ │ ├── property.component.scss │ │ │ │ ├── property.component.spec.ts │ │ │ │ └── property.component.ts │ │ │ ├── remove │ │ │ │ ├── remove.component.html │ │ │ │ ├── remove.component.scss │ │ │ │ ├── remove.component.spec.ts │ │ │ │ └── remove.component.ts │ │ │ ├── rename │ │ │ │ ├── rename.component.html │ │ │ │ ├── rename.component.scss │ │ │ │ ├── rename.component.spec.ts │ │ │ │ └── rename.component.ts │ │ │ ├── uncompress │ │ │ │ ├── state.ts │ │ │ │ ├── uncompress.component.html │ │ │ │ ├── uncompress.component.scss │ │ │ │ ├── uncompress.component.spec.ts │ │ │ │ └── uncompress.component.ts │ │ │ └── upload │ │ │ │ ├── hash.worker.ts │ │ │ │ ├── load_state.ts │ │ │ │ ├── state.ts │ │ │ │ ├── upload.component.html │ │ │ │ ├── upload.component.scss │ │ │ │ ├── upload.component.spec.ts │ │ │ │ ├── upload.component.ts │ │ │ │ └── uploader.ts │ │ ├── file │ │ │ ├── file.component.html │ │ │ ├── file.component.scss │ │ │ ├── file.component.spec.ts │ │ │ └── file.component.ts │ │ ├── forward-fs-routing.module.ts │ │ ├── forward-fs.module.ts │ │ ├── fs.ts │ │ ├── list │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.spec.ts │ │ │ ├── list.component.ts │ │ │ ├── load_state.ts │ │ │ └── state.ts │ │ ├── manager │ │ │ ├── box.ts │ │ │ ├── manager.component.html │ │ │ ├── manager.component.scss │ │ │ ├── manager.component.spec.ts │ │ │ ├── manager.component.ts │ │ │ └── settings.ts │ │ ├── navigation │ │ │ ├── navigation.component.html │ │ │ ├── navigation.component.scss │ │ │ ├── navigation.component.spec.ts │ │ │ └── navigation.component.ts │ │ ├── path │ │ │ ├── path.component.html │ │ │ ├── path.component.scss │ │ │ ├── path.component.spec.ts │ │ │ └── path.component.ts │ │ ├── plugins │ │ │ └── movie │ │ │ │ ├── db.ts │ │ │ │ ├── manager.ts │ │ │ │ ├── movie.component.html │ │ │ │ ├── movie.component.scss │ │ │ │ ├── movie.component.spec.ts │ │ │ │ └── movie.component.ts │ │ ├── root │ │ │ ├── load_state.ts │ │ │ ├── root.component.html │ │ │ ├── root.component.scss │ │ │ ├── root.component.spec.ts │ │ │ ├── root.component.ts │ │ │ └── state.ts │ │ └── view │ │ │ ├── audio │ │ │ ├── audio.component.html │ │ │ ├── audio.component.scss │ │ │ ├── audio.component.spec.ts │ │ │ └── audio.component.ts │ │ │ ├── image │ │ │ ├── image.component.html │ │ │ ├── image.component.scss │ │ │ ├── image.component.spec.ts │ │ │ └── image.component.ts │ │ │ ├── text │ │ │ ├── text.component.html │ │ │ ├── text.component.scss │ │ │ ├── text.component.spec.ts │ │ │ ├── text.component.ts │ │ │ ├── text.guard.spec.ts │ │ │ └── text.guard.ts │ │ │ └── video │ │ │ ├── video.component.html │ │ │ ├── video.component.scss │ │ │ ├── video.component.spec.ts │ │ │ └── video.component.ts │ ├── forward-logger │ │ ├── attach │ │ │ ├── attach.component.html │ │ │ ├── attach.component.scss │ │ │ ├── attach.component.spec.ts │ │ │ ├── attach.component.ts │ │ │ └── listener.ts │ │ ├── download │ │ │ ├── download.component.html │ │ │ ├── download.component.scss │ │ │ ├── download.component.spec.ts │ │ │ └── download.component.ts │ │ ├── forward-logger-routing.module.ts │ │ ├── forward-logger.module.ts │ │ └── view │ │ │ ├── view.component.html │ │ │ ├── view.component.scss │ │ │ ├── view.component.spec.ts │ │ │ └── view.component.ts │ ├── forward-shell │ │ ├── dialog │ │ │ ├── delete │ │ │ │ ├── delete.component.html │ │ │ │ ├── delete.component.scss │ │ │ │ ├── delete.component.spec.ts │ │ │ │ └── delete.component.ts │ │ │ ├── edit │ │ │ │ ├── edit.component.html │ │ │ │ ├── edit.component.scss │ │ │ │ ├── edit.component.spec.ts │ │ │ │ └── edit.component.ts │ │ │ └── settings │ │ │ │ ├── settings.component.html │ │ │ │ ├── settings.component.scss │ │ │ │ ├── settings.component.spec.ts │ │ │ │ └── settings.component.ts │ │ ├── forward-shell-routing.module.ts │ │ ├── forward-shell.module.ts │ │ ├── list │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.spec.ts │ │ │ ├── list.component.ts │ │ │ ├── load_state.ts │ │ │ └── state.ts │ │ └── view │ │ │ ├── state.ts │ │ │ ├── view.component.html │ │ │ ├── view.component.scss │ │ │ ├── view.component.spec.ts │ │ │ └── view.component.ts │ ├── forward │ │ ├── forward-routing.module.ts │ │ ├── forward.module.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.spec.ts │ │ │ ├── home.component.ts │ │ │ ├── load_state.ts │ │ │ └── state.ts │ │ └── shared │ │ │ ├── load_state.ts │ │ │ ├── shared.component.html │ │ │ ├── shared.component.scss │ │ │ ├── shared.component.spec.ts │ │ │ ├── shared.component.ts │ │ │ └── state.ts │ ├── group │ │ ├── dialog │ │ │ ├── add │ │ │ │ ├── add.component.html │ │ │ │ ├── add.component.scss │ │ │ │ ├── add.component.spec.ts │ │ │ │ └── add.component.ts │ │ │ ├── delete │ │ │ │ ├── delete.component.html │ │ │ │ ├── delete.component.scss │ │ │ │ ├── delete.component.spec.ts │ │ │ │ └── delete.component.ts │ │ │ ├── edit │ │ │ │ ├── edit.component.html │ │ │ │ ├── edit.component.scss │ │ │ │ ├── edit.component.spec.ts │ │ │ │ └── edit.component.ts │ │ │ └── select │ │ │ │ ├── select.component.html │ │ │ │ ├── select.component.scss │ │ │ │ ├── select.component.spec.ts │ │ │ │ └── select.component.ts │ │ ├── group-routing.module.ts │ │ ├── group.module.ts │ │ └── list │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.spec.ts │ │ │ ├── list.component.ts │ │ │ └── node │ │ │ ├── node.component.html │ │ │ ├── node.component.scss │ │ │ ├── node.component.spec.ts │ │ │ └── node.component.ts │ ├── logger │ │ ├── attach │ │ │ ├── attach.component.html │ │ │ ├── attach.component.scss │ │ │ ├── attach.component.spec.ts │ │ │ ├── attach.component.ts │ │ │ └── listener.ts │ │ ├── download │ │ │ ├── download.component.html │ │ │ ├── download.component.scss │ │ │ ├── download.component.spec.ts │ │ │ └── download.component.ts │ │ ├── logger-routing.module.ts │ │ ├── logger.module.ts │ │ └── view │ │ │ ├── view.component.html │ │ │ ├── view.component.scss │ │ │ ├── view.component.spec.ts │ │ │ └── view.component.ts │ ├── package.json │ ├── shared │ │ ├── load-view │ │ │ ├── load-view.component.html │ │ │ ├── load-view.component.scss │ │ │ ├── load-view.component.spec.ts │ │ │ └── load-view.component.ts │ │ ├── navigation-bar │ │ │ ├── navigation-bar.component.html │ │ │ ├── navigation-bar.component.scss │ │ │ ├── navigation-bar.component.spec.ts │ │ │ └── navigation-bar.component.ts │ │ ├── password │ │ │ ├── password.component.html │ │ │ ├── password.component.scss │ │ │ ├── password.component.spec.ts │ │ │ └── password.component.ts │ │ ├── shared.module.ts │ │ ├── sign-in │ │ │ ├── sign-in.component.html │ │ │ ├── sign-in.component.scss │ │ │ ├── sign-in.component.spec.ts │ │ │ └── sign-in.component.ts │ │ ├── tree-select │ │ │ ├── tree-select.component.html │ │ │ ├── tree-select.component.scss │ │ │ ├── tree-select.component.spec.ts │ │ │ └── tree-select.component.ts │ │ ├── tree │ │ │ ├── tree.component.html │ │ │ ├── tree.component.scss │ │ │ ├── tree.component.spec.ts │ │ │ └── tree.component.ts │ │ └── upgraded │ │ │ ├── upgraded.component.html │ │ │ ├── upgraded.component.scss │ │ │ ├── upgraded.component.spec.ts │ │ │ └── upgraded.component.ts │ └── user │ │ ├── dialog │ │ ├── add │ │ │ ├── add.component.html │ │ │ ├── add.component.scss │ │ │ ├── add.component.spec.ts │ │ │ └── add.component.ts │ │ ├── delete │ │ │ ├── delete.component.html │ │ │ ├── delete.component.scss │ │ │ ├── delete.component.spec.ts │ │ │ └── delete.component.ts │ │ ├── edit │ │ │ ├── edit.component.html │ │ │ ├── edit.component.scss │ │ │ ├── edit.component.spec.ts │ │ │ └── edit.component.ts │ │ ├── group │ │ │ ├── group.component.html │ │ │ ├── group.component.scss │ │ │ ├── group.component.spec.ts │ │ │ └── group.component.ts │ │ └── password │ │ │ ├── password.component.html │ │ │ ├── password.component.scss │ │ │ ├── password.component.spec.ts │ │ │ └── password.component.ts │ │ ├── query │ │ ├── query.component.html │ │ ├── query.component.scss │ │ ├── query.component.spec.ts │ │ ├── query.component.ts │ │ └── query.ts │ │ ├── user-routing.module.ts │ │ └── user.module.ts ├── assets │ ├── .gitkeep │ └── icons │ │ ├── icon-128x128.png │ │ ├── icon-144x144.png │ │ ├── icon-152x152.png │ │ ├── icon-192x192.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ ├── icon-72x72.png │ │ └── icon-96x96.png ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── index.html ├── locale │ ├── en-US.xlf │ ├── zh-Hans.xlf │ └── zh-Hant.xlf ├── main.ts ├── manifest.webmanifest ├── polyfills.ts ├── styles.scss └── test.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json ├── tsconfig.worker.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | /vendor/ 15 | *.gz 16 | *.bz 17 | *.bz2 18 | *.xz 19 | *.7z 20 | *.zip 21 | *.db 22 | *.log 23 | *.sha256 24 | *.sha256.txt 25 | 26 | /static/3rdpartylicenses.txt 27 | 28 | /.tmp/ 29 | /webpc 30 | /webpcd 31 | /bin/webpc 32 | /bin/webpcd 33 | /bin/var/logs/ 34 | /bin/upgrade-data/ 35 | 36 | # grpc code 37 | /protocol/ 38 | /bin/protocol/ 39 | /static/document/api/ 40 | /static/view/ -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch file", 9 | "type": "go", 10 | "request": "launch", 11 | "mode": "debug", 12 | "program": "${workspaceRoot}/main.go", 13 | "args": [ 14 | "master", 15 | "-d", 16 | "-c", 17 | "${workspaceRoot}/bin/etc/master.jsonnet" 18 | ] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /bin/controller.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set CURRENT_DIR=%~dp0 3 | cd %CURRENT_DIR% 4 | %CURRENT_DIR:~0,2% 5 | 6 | :AGAIN 7 | echo * 0 cancel execute 8 | echo * 1 install master 9 | echo * 2 install slave 10 | echo * 3 uninstall master 11 | echo * 4 uninstall slave 12 | 13 | set choice=-1 14 | set /p choice=choice commnad: 15 | if "%choice%"=="0" ( 16 | goto END 17 | ) 18 | if "%choice%"=="1" ( 19 | webpc-master install 20 | pause 21 | goto END 22 | ) 23 | if "%choice%"=="2" ( 24 | webpc-slave install 25 | pause 26 | goto END 27 | ) 28 | if "%choice%"=="3" ( 29 | webpc-master uninstall 30 | pause 31 | goto END 32 | ) 33 | if "%choice%"=="4" ( 34 | webpc-slave uninstall 35 | pause 36 | goto END 37 | ) 38 | goto AGAIN 39 | 40 | :END 41 | -------------------------------------------------------------------------------- /bin/etc/master.jsonnet: -------------------------------------------------------------------------------- 1 | { 2 | HTTP: import 'master/http.libsonnet', 3 | System: import 'master/system.libsonnet', 4 | DB: import 'master/db.libsonnet', 5 | Session: import 'master/session.libsonnet', 6 | Logger: import 'master/logger.libsonnet', 7 | } -------------------------------------------------------------------------------- /bin/etc/master/db.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local driver = def.Driver; 3 | { 4 | Driver: driver.Sqlite3, 5 | Source: [ 6 | 'var/webpc_master.db', 7 | ], 8 | // max connections if < 1 not not limited 9 | MaxOpen: 50, 10 | // idle connections if < 1 not exists idle 11 | MaxIdle: 5, 12 | // ShowSQL: true, 13 | Cache: { 14 | // default cache rows 15 | Record: 1000, 16 | // disable cache table names 17 | Direct: [], 18 | // special cache 19 | Special: [ 20 | { 21 | Name: 'data_of_user', 22 | Record: 100, 23 | }, 24 | { 25 | Name: 'data_of_slave', 26 | Record: 100, 27 | }, 28 | ], 29 | }, 30 | } -------------------------------------------------------------------------------- /bin/etc/master/logger.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local level = def.Level; 3 | { 4 | // log file name 5 | Filename: 'var/logs/master/webpc.log', 6 | // Maximum size of a single log file 7 | // MB 8 | MaxSize: 100, 9 | // How many log files are saved 10 | MaxBackups: 3, 11 | // How many days of logs are kept 12 | MaxDays: 28, 13 | // Do you want to output the code location 14 | // Caller: true, 15 | // debug info warn error dpanic panic fatal 16 | FileLevel: level.Info, 17 | // debug info warn error dpanic panic fatal 18 | ConsoleLevel: level.Debug, 19 | } -------------------------------------------------------------------------------- /bin/etc/slave.jsonnet: -------------------------------------------------------------------------------- 1 | { 2 | Connect: import 'slave/connect.libsonnet', 3 | System: import 'slave/system.libsonnet', 4 | DB: import 'slave/db.libsonnet', 5 | Logger: import 'slave/logger.libsonnet', 6 | } -------------------------------------------------------------------------------- /bin/etc/slave/db.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local driver = def.Driver; 3 | { 4 | Driver: driver.Sqlite3, 5 | Source: [ 6 | 'var/webpc_slave.db', 7 | ], 8 | // max connections if < 1 not not limited 9 | MaxOpen: 50, 10 | // idle connections if < 1 not exists idle 11 | MaxIdle: 5, 12 | // ShowSQL: true, 13 | Cache: { 14 | // default cache rows 15 | Record: 1000, 16 | // disable cache table names 17 | Direct: [], 18 | // special cache 19 | Special: [ 20 | ], 21 | }, 22 | } -------------------------------------------------------------------------------- /bin/etc/slave/logger.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local level = def.Level; 3 | { 4 | // log file name 5 | Filename: 'var/logs/slave/webpc.log', 6 | // Maximum size of a single log file 7 | // MB 8 | MaxSize: 100, 9 | // How many log files are saved 10 | MaxBackups: 3, 11 | // How many days of logs are kept 12 | MaxDays: 28, 13 | // Do you want to output the code location 14 | // Caller: true, 15 | // debug info warn error dpanic panic fatal 16 | FileLevel: level.Info, 17 | // debug info warn error dpanic panic fatal 18 | ConsoleLevel: level.Debug, 19 | } -------------------------------------------------------------------------------- /bin/nginx_webpc.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | # listen 443 ssl http2; 4 | # ssl_certificate your_tls_crt; 5 | # ssl_certificate_key your_tls_key; 6 | 7 | # server_name your_domain; 8 | 9 | client_max_body_size 5M; 10 | charset utf8; 11 | 12 | location / { 13 | proxy_set_header Origin 'http://$host'; 14 | 15 | proxy_http_version 1.1; 16 | proxy_set_header Upgrade $http_upgrade; 17 | proxy_set_header Connection $http_connection; 18 | proxy_set_header Host $host; 19 | proxy_set_header X-Real-IP $remote_addr; 20 | proxy_set_header REMOTE-HOST $remote_addr; 21 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 22 | proxy_set_header X-Forwarded-Ssl on; 23 | 24 | # proxy_pass http://your_webpc_listen; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bin/run-linux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export TERM=xterm 3 | export HOME="/home/$1" 4 | Dir=$(cd "$(dirname $BASH_SOURCE)" && pwd) 5 | sudo -u "$1" "$Dir/shell-linux" "$1 -------------------------------------------------------------------------------- /bin/service.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/bin/service.bat -------------------------------------------------------------------------------- /bin/shell-bash.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :loop 4 | echo Welcome %ShellUser% shell as %UserName% 5 | 6 | E:\opt\msys64\usr\bin\bash -l 7 | 8 | :read 9 | set quit=nil 10 | 11 | set /p quit="Are you sure you want to close the shell : " 12 | 13 | if "%quit%"=="y" goto end 14 | if "%quit%"=="yes" goto end 15 | 16 | if "%quit%"=="n" goto loop 17 | if "%quit%"=="no" goto loop 18 | 19 | goto read 20 | 21 | :end 22 | echo bye %ShellUser% of %UserName% 23 | 24 | timeout /t 1 -------------------------------------------------------------------------------- /bin/shell-linux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export TERM=xterm 3 | cd ~ 4 | 5 | declare -i x 6 | x=0 7 | while [ $x -lt 1 ] 8 | do 9 | echo "Welcome $1" 10 | bash -l 11 | while true 12 | do 13 | echo '' 14 | read -p "Are you sure you want to close the shell : " quit 15 | if [ "$quit" == 'y' -o "$quit" == 'yes' ];then 16 | x=1 17 | break 18 | elif [ "$quit" == 'n' -o "$quit" == 'no' ];then 19 | break 20 | fi 21 | done 22 | done 23 | 24 | echo "bye $1" -------------------------------------------------------------------------------- /bin/shell-windows.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :loop 4 | echo Welcome %ShellUser% shell as %UserName% 5 | cmd 6 | 7 | :read 8 | set quit=nil 9 | 10 | set /p quit="Are you sure you want to close the shell : " 11 | 12 | if "%quit%"=="y" goto end 13 | if "%quit%"=="yes" goto end 14 | 15 | if "%quit%"=="n" goto loop 16 | if "%quit%"=="no" goto loop 17 | 18 | goto read 19 | 20 | :end 21 | echo bye %ShellUser% of %UserName% 22 | 23 | timeout /t 1 -------------------------------------------------------------------------------- /bin/useradd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | useradd webpc -Mrs /sbin/nologin -------------------------------------------------------------------------------- /bin/webpc-master.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/bin/webpc-master.exe -------------------------------------------------------------------------------- /bin/webpc-master.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=WebPC Master Service 3 | After=network.target 4 | 5 | [Service] 6 | User=webpc 7 | Type=simple 8 | WorkingDirectory=/opt/webpc 9 | ExecStart=/opt/webpc/webpc master 10 | KillMode=control-group 11 | Restart=on-failure 12 | LimitNOFILE=100000 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /bin/webpc-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | webpc-master-service 4 | WebPC Master Service 5 | WebPC Master Service 6 | %BASE% 7 | %BASE%\webpc 8 | master 9 | 10 | 11 | -------------------------------------------------------------------------------- /bin/webpc-slave.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/bin/webpc-slave.exe -------------------------------------------------------------------------------- /bin/webpc-slave.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=WebPC Slave Service 3 | After=network.target 4 | 5 | [Service] 6 | User=webpc 7 | Type=simple 8 | WorkingDirectory=/opt/webpc 9 | ExecStart=/opt/webpc/webpc slave 10 | KillMode=control-group 11 | Restart=on-failure 12 | LimitNOFILE=100000 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /bin/webpc-slave.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | webpc-slave-service 4 | WebPC Slave Service 5 | WebPC Slave Service 6 | %BASE% 7 | %BASE%\webpc 8 | slave 9 | 10 | 11 | -------------------------------------------------------------------------------- /bin/winpty-agent.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/bin/winpty-agent.exe -------------------------------------------------------------------------------- /bin/winpty.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/bin/winpty.dll -------------------------------------------------------------------------------- /cmd/internal/master/system.go: -------------------------------------------------------------------------------- 1 | package master 2 | 3 | import ( 4 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 5 | "github.com/powerpuffpenguin/webpc/configure" 6 | "github.com/powerpuffpenguin/webpc/m/forward" 7 | "github.com/powerpuffpenguin/webpc/slave" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func registerSystem(srv *grpc.Server, system *configure.System, cc *grpc.ClientConn, gateway *runtime.ServeMux) (e error) { 12 | if !system.Enable { 13 | return 14 | } 15 | e = slave.HTTP(gateway, cc) 16 | if e != nil { 17 | return 18 | } 19 | slave.GRPC(srv) 20 | 21 | forward.Default().Put(0, cc, gateway) 22 | return 23 | } 24 | -------------------------------------------------------------------------------- /configure/db.go: -------------------------------------------------------------------------------- 1 | package configure 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/powerpuffpenguin/webpc/utils" 7 | ) 8 | 9 | type DB struct { 10 | Driver string 11 | Source []string 12 | ShowSQL bool 13 | 14 | Cache struct { 15 | Record int 16 | Direct []string 17 | Special []struct { 18 | Name string 19 | Record int 20 | } 21 | } 22 | MaxOpen, MaxIdle int 23 | } 24 | 25 | func (d *DB) format() (e error) { 26 | d.Driver = strings.ToLower(strings.TrimSpace(d.Driver)) 27 | if d.Driver == "sqlite3" { 28 | basePath := utils.BasePath() 29 | for i, source := range d.Source { 30 | d.Source[i] = utils.Abs(basePath, source) 31 | } 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /db/const.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | const ( 4 | // super administrator has all permissions 5 | Root = 1 6 | // access server 7 | Server = 2 8 | // web shell 9 | Shell = 3 10 | // filesystem read 11 | Read = 4 12 | // filesystem write 13 | Write = 5 14 | // vnc view 15 | VNC = 6 16 | // add edit delete of slave 17 | Slave = 7 18 | // allow port forwarding 19 | PortForward = 8 20 | ) 21 | -------------------------------------------------------------------------------- /db/data/modtime.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | const ( 4 | TableModtimeName = `modtime` 5 | ColModtimeID = `id` 6 | ColModtimeUnix = `unix` 7 | ColModtimeETag = `etag` 8 | ColModtimeDescription = `description` 9 | ) 10 | 11 | type Modtime struct { 12 | ID int32 `xorm:"pk 'id'"` 13 | Unix int64 `xorm:"'unix'"` 14 | ETag string `xorm:"'etag'"` 15 | Description string `xorm:"'description'"` 16 | } 17 | 18 | func (Modtime) TableName() string { 19 | return TableModtimeName 20 | } 21 | -------------------------------------------------------------------------------- /docker/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/docker/1.png -------------------------------------------------------------------------------- /docker/source/etc/master.jsonnet: -------------------------------------------------------------------------------- 1 | { 2 | HTTP: import 'master/http.libsonnet', 3 | System: import 'master/system.libsonnet', 4 | DB: import 'master/db.libsonnet', 5 | Session: import 'master/session.libsonnet', 6 | Logger: import 'master/logger.libsonnet', 7 | } -------------------------------------------------------------------------------- /docker/source/etc/master/db.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local driver = def.Driver; 3 | { 4 | Driver: driver.Sqlite3, 5 | Source: [ 6 | 'var/webpc_master.db', 7 | ], 8 | // max connections if < 1 not not limited 9 | MaxOpen: 50, 10 | // idle connections if < 1 not exists idle 11 | MaxIdle: 5, 12 | // ShowSQL: true, 13 | Cache: { 14 | // default cache rows 15 | Record: 1000, 16 | // disable cache table names 17 | Direct: [], 18 | // special cache 19 | Special: [ 20 | { 21 | Name: 'data_of_user', 22 | Record: 100, 23 | }, 24 | { 25 | Name: 'data_of_slave', 26 | Record: 100, 27 | }, 28 | ], 29 | }, 30 | } -------------------------------------------------------------------------------- /docker/source/etc/master/logger.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local level = def.Level; 3 | { 4 | // log file name 5 | Filename: 'var/logs/master/webpc.log', 6 | // Maximum size of a single log file 7 | // MB 8 | MaxSize: 100, 9 | // How many log files are saved 10 | MaxBackups: 3, 11 | // How many days of logs are kept 12 | MaxDays: 28, 13 | // Do you want to output the code location 14 | // Caller: true, 15 | // debug info warn error dpanic panic fatal 16 | FileLevel: level.Info, 17 | // debug info warn error dpanic panic fatal 18 | ConsoleLevel: level.Debug, 19 | } -------------------------------------------------------------------------------- /docker/source/etc/master/system.libsonnet: -------------------------------------------------------------------------------- 1 | { 2 | // Register the master server as a virtual slave to allow web access 3 | Enable: true, 4 | //Shell : "shell-linux", // if empty, linux default value shell-linux.sh 5 | //Shell : "shell-windows.bat", // if empty, windows default value shell-windows.bat 6 | // vnc server address 7 | VNC: "127.0.0.1:5900", 8 | // if true allow port forwarding 9 | PortForward: true, 10 | // mount path to web 11 | Mount: [ 12 | { 13 | Name: "fs", 14 | Root: "/opt/webpc/fs", 15 | Write: true, 16 | Read: true, 17 | Shared: false, 18 | }, 19 | { 20 | Name: "root", 21 | Root: "/", 22 | Write: false, 23 | Read: true, 24 | Shared: false, 25 | }, 26 | ], 27 | } -------------------------------------------------------------------------------- /docker/source/etc/slave.jsonnet: -------------------------------------------------------------------------------- 1 | { 2 | Connect: import 'slave/connect.libsonnet', 3 | System: import 'slave/system.libsonnet', 4 | DB: import 'slave/db.libsonnet', 5 | Logger: import 'slave/logger.libsonnet', 6 | } -------------------------------------------------------------------------------- /docker/source/etc/slave/db.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local driver = def.Driver; 3 | { 4 | Driver: driver.Sqlite3, 5 | Source: [ 6 | 'var/webpc_slave.db', 7 | ], 8 | // max connections if < 1 not not limited 9 | MaxOpen: 50, 10 | // idle connections if < 1 not exists idle 11 | MaxIdle: 5, 12 | // ShowSQL: true, 13 | Cache: { 14 | // default cache rows 15 | Record: 1000, 16 | // disable cache table names 17 | Direct: [], 18 | // special cache 19 | Special: [ 20 | ], 21 | }, 22 | } -------------------------------------------------------------------------------- /docker/source/etc/slave/logger.libsonnet: -------------------------------------------------------------------------------- 1 | local def = import "def.libsonnet"; 2 | local level = def.Level; 3 | { 4 | // log file name 5 | Filename: 'var/logs/slave/webpc.log', 6 | // Maximum size of a single log file 7 | // MB 8 | MaxSize: 100, 9 | // How many log files are saved 10 | MaxBackups: 3, 11 | // How many days of logs are kept 12 | MaxDays: 28, 13 | // Do you want to output the code location 14 | // Caller: true, 15 | // debug info warn error dpanic panic fatal 16 | FileLevel: level.Info, 17 | // debug info warn error dpanic panic fatal 18 | ConsoleLevel: level.Debug, 19 | } -------------------------------------------------------------------------------- /docker/source/etc/slave/system.libsonnet: -------------------------------------------------------------------------------- 1 | { 2 | //Shell : "shell-linux", // if empty, linux default value shell-linux.sh 3 | //Shell : "shell-windows.bat", // if empty, windows default value shell-windows.bat 4 | // vnc server address 5 | VNC: "127.0.0.1:5900", 6 | // if true allow port forwarding 7 | PortForward: true, 8 | // mount path to web 9 | Mount: [ 10 | { 11 | Name: "fs", 12 | Root: "/opt/webpc/fs", 13 | Write: true, 14 | Read: true, 15 | Shared: false, 16 | }, 17 | { 18 | Name: "root", 19 | Root: "/", 20 | Write: false, 21 | Read: true, 22 | Shared: false, 23 | }, 24 | ], 25 | } -------------------------------------------------------------------------------- /document/fs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/document/fs.gif -------------------------------------------------------------------------------- /document/shell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/document/shell.gif -------------------------------------------------------------------------------- /document/vnc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/document/vnc.gif -------------------------------------------------------------------------------- /logger/init.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import "path/filepath" 4 | 5 | // Logger logger single 6 | var Logger Helper 7 | 8 | // Init init logger 9 | func Init(basePath string, master bool, options *Options) (e error) { 10 | if options.Filename == `` { 11 | if master { 12 | options.Filename = filepath.Clean(filepath.Join(basePath, `var`, `logs`, `master`, `webpc.log`)) 13 | } else { 14 | options.Filename = filepath.Clean(filepath.Join(basePath, `var`, `logs`, `slave`, `webpc.log`)) 15 | } 16 | } else { 17 | if filepath.IsAbs(options.Filename) { 18 | options.Filename = filepath.Clean(options.Filename) 19 | } else { 20 | options.Filename = filepath.Clean(filepath.Join(basePath, options.Filename)) 21 | } 22 | } 23 | Logger.Attach(NewHelper(options)) 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /logger/init_console.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "os" 5 | 6 | "go.uber.org/zap" 7 | "go.uber.org/zap/zapcore" 8 | ) 9 | 10 | func InitConsole(level string) { 11 | var zapOptions []zap.Option 12 | lv := zap.NewAtomicLevel() 13 | if level == `` { 14 | lv.SetLevel(zap.InfoLevel) 15 | } else if e := lv.UnmarshalText([]byte(level)); e != nil { 16 | lv.SetLevel(zap.InfoLevel) 17 | } 18 | Logger.Attach(&Helper{ 19 | Logger: zap.New( 20 | zapcore.NewCore( 21 | zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), 22 | os.Stdout, 23 | lv, 24 | ), 25 | zapOptions..., 26 | ), 27 | fileLevel: lv, 28 | consoleLevel: lv, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /m/helper/helper.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "google.golang.org/grpc/codes" 5 | "google.golang.org/grpc/status" 6 | ) 7 | 8 | type Helper int 9 | 10 | func (Helper) Error(c codes.Code, msg string) error { 11 | return status.Error(c, msg) 12 | } 13 | func (Helper) Errorf(c codes.Code, format string, a ...interface{}) error { 14 | return status.Errorf(c, format, a...) 15 | } 16 | -------------------------------------------------------------------------------- /m/server/group/auth.go: -------------------------------------------------------------------------------- 1 | package group 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/powerpuffpenguin/webpc/db" 8 | 9 | "google.golang.org/grpc/codes" 10 | ) 11 | 12 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 13 | ctx, userdata, e := s.Userdata(ctx) 14 | if e != nil { 15 | return ctx, e 16 | } else if strings.HasSuffix(fullMethodName, `/List`) || 17 | userdata.AuthAny(db.Root) { 18 | return ctx, nil 19 | } 20 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 21 | } 22 | -------------------------------------------------------------------------------- /m/server/group/init.go: -------------------------------------------------------------------------------- 1 | package group 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 7 | tree "github.com/powerpuffpenguin/webpc/m/server/group/internal/tree" 8 | grpc_group "github.com/powerpuffpenguin/webpc/protocol/group" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_group.RegisterGroupServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | tree.Default().Init() 19 | return grpc_group.RegisterGroupHandler(context.Background(), gateway, cc) 20 | } 21 | -------------------------------------------------------------------------------- /m/server/group/internal/db/data.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | const ( 4 | tableName = `data_of_group` 5 | 6 | colID = `id` 7 | colParent = `parent` 8 | colName = `name` 9 | colDescription = `description` 10 | ) 11 | 12 | type DataOfGroup struct { 13 | ID int64 `xorm:"pk autoincr 'id'"` 14 | Parent int64 `xorm:"'parent' default(0)"` 15 | Name string `xorm:"unique 'name' default('') "` 16 | Description string `xorm:"'description' default('') "` 17 | } 18 | 19 | func (DataOfGroup) TableName() string { 20 | return tableName 21 | } 22 | -------------------------------------------------------------------------------- /m/server/logger/auth.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "context" 5 | "github.com/powerpuffpenguin/webpc/db" 6 | 7 | "google.golang.org/grpc/codes" 8 | ) 9 | 10 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 11 | ctx, userdata, e := s.Userdata(ctx) 12 | if e != nil { 13 | return ctx, e 14 | } else if userdata.AuthAny(db.Root) { 15 | return ctx, nil 16 | } 17 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 18 | } 19 | -------------------------------------------------------------------------------- /m/server/logger/init.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "context" 5 | 6 | grpc_logger "github.com/powerpuffpenguin/webpc/protocol/logger" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_logger.RegisterLoggerServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | return grpc_logger.RegisterLoggerHandler(context.Background(), gateway, cc) 19 | } 20 | -------------------------------------------------------------------------------- /m/server/session/init.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "context" 5 | grpc_session "github.com/powerpuffpenguin/webpc/protocol/session" 6 | 7 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | type Module int 12 | 13 | func (Module) RegisterGRPC(srv *grpc.Server) { 14 | grpc_session.RegisterSessionServer(srv, server{}) 15 | } 16 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 17 | return grpc_session.RegisterSessionHandler(context.Background(), gateway, cc) 18 | } 19 | -------------------------------------------------------------------------------- /m/server/slave/auth.go: -------------------------------------------------------------------------------- 1 | package slave 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/powerpuffpenguin/webpc/db" 8 | 9 | "google.golang.org/grpc/codes" 10 | ) 11 | 12 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 13 | ctx, userdata, e := s.Userdata(ctx) 14 | if e != nil { 15 | return ctx, e 16 | } else if strings.HasSuffix(fullMethodName, `/Find`) || 17 | strings.HasSuffix(fullMethodName, `/Get`) || 18 | strings.HasSuffix(fullMethodName, `/Subscribe`) || 19 | userdata.AuthAny(db.Root, db.Slave) { 20 | return ctx, nil 21 | } 22 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 23 | } 24 | -------------------------------------------------------------------------------- /m/server/slave/init.go: -------------------------------------------------------------------------------- 1 | package slave 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/powerpuffpenguin/webpc/m/server/slave/internal/db" 7 | grpc_slave "github.com/powerpuffpenguin/webpc/protocol/slave" 8 | 9 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | type Module int 14 | 15 | func (Module) RegisterGRPC(srv *grpc.Server) { 16 | grpc_slave.RegisterSlaveServer(srv, server{}) 17 | } 18 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 19 | db.Init() 20 | return grpc_slave.RegisterSlaveHandler(context.Background(), gateway, cc) 21 | } 22 | -------------------------------------------------------------------------------- /m/server/system/auth.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "context" 5 | "github.com/powerpuffpenguin/webpc/db" 6 | 7 | "google.golang.org/grpc/codes" 8 | ) 9 | 10 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 11 | ctx, userdata, e := s.Userdata(ctx) 12 | if e != nil { 13 | return ctx, e 14 | } else if userdata.AuthAny(db.Root) { 15 | return ctx, nil 16 | } 17 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 18 | } 19 | -------------------------------------------------------------------------------- /m/server/system/init.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "context" 5 | grpc_system "github.com/powerpuffpenguin/webpc/protocol/system" 6 | "time" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_system.RegisterSystemServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | startAtResponse.Result = time.Now().Unix() 19 | return grpc_system.RegisterSystemHandler(context.Background(), gateway, cc) 20 | } 21 | -------------------------------------------------------------------------------- /m/server/user/auth.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "context" 5 | "github.com/powerpuffpenguin/webpc/db" 6 | 7 | "google.golang.org/grpc/codes" 8 | ) 9 | 10 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 11 | ctx, userdata, e := s.Userdata(ctx) 12 | if e != nil { 13 | return ctx, e 14 | } else if userdata.AuthAny(db.Root) { 15 | return ctx, nil 16 | } 17 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 18 | } 19 | -------------------------------------------------------------------------------- /m/server/user/init.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "context" 5 | "github.com/powerpuffpenguin/webpc/m/server/user/internal/db" 6 | grpc_user "github.com/powerpuffpenguin/webpc/protocol/user" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_user.RegisterUserServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | db.Init() 19 | return grpc_user.RegisterUserHandler(context.Background(), gateway, cc) 20 | } 21 | -------------------------------------------------------------------------------- /m/web/api/forward/init.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/powerpuffpenguin/webpc/m/web" 6 | v1 "github.com/powerpuffpenguin/webpc/m/web/api/forward/v1" 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | const BaseURL = `forward` 11 | 12 | type Helper struct { 13 | web.Helper 14 | } 15 | 16 | func (h Helper) Register(cc *grpc.ClientConn, router *gin.RouterGroup) { 17 | r := router.Group(BaseURL) 18 | 19 | ms := []web.IHelper{ 20 | v1.Helper{}, 21 | } 22 | for _, m := range ms { 23 | m.Register(cc, r) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /m/web/api/forward/v1/init.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/powerpuffpenguin/webpc/m/web" 6 | "google.golang.org/grpc" 7 | ) 8 | 9 | const BaseURL = `v1` 10 | 11 | type Helper struct { 12 | web.Helper 13 | } 14 | 15 | func (h Helper) Register(cc *grpc.ClientConn, router *gin.RouterGroup) { 16 | r := router.Group(BaseURL) 17 | 18 | ms := []web.IHelper{ 19 | Filesystem{}, 20 | Static{}, 21 | Logger{}, 22 | Shell{}, 23 | VNC{}, 24 | Forward{}, 25 | } 26 | for _, m := range ms { 27 | m.Register(cc, r) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /m/web/api/v1/init.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/powerpuffpenguin/webpc/m/web" 6 | "google.golang.org/grpc" 7 | ) 8 | 9 | const BaseURL = `v1` 10 | 11 | type Helper struct { 12 | web.Helper 13 | } 14 | 15 | func (h Helper) Register(cc *grpc.ClientConn, router *gin.RouterGroup) { 16 | r := router.Group(BaseURL) 17 | 18 | ms := []web.IHelper{ 19 | &Logger{}, 20 | Dialer{}, 21 | &Slave{}, 22 | } 23 | for _, m := range ms { 24 | m.Register(cc, r) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /m/web/api/v1/internal/dialer/conn.go: -------------------------------------------------------------------------------- 1 | package dialer 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | type Conn struct { 8 | id int64 9 | net.Conn 10 | close chan struct{} 11 | callback func(id int64) 12 | } 13 | 14 | func NewConn(id int64, c net.Conn) *Conn { 15 | return &Conn{ 16 | id: id, 17 | Conn: c, 18 | close: make(chan struct{}), 19 | } 20 | } 21 | func (c *Conn) Close() (e error) { 22 | e = c.Conn.Close() 23 | if e == nil { 24 | close(c.close) 25 | if c.callback != nil { 26 | c.callback(c.id) 27 | } 28 | } 29 | return 30 | } 31 | func (c *Conn) Done() <-chan struct{} { 32 | return c.close 33 | } 34 | -------------------------------------------------------------------------------- /m/web/types.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "google.golang.org/grpc" 6 | ) 7 | 8 | type IHelper interface { 9 | Register(*grpc.ClientConn, *gin.RouterGroup) 10 | } 11 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/powerpuffpenguin/webpc/cmd" 7 | 8 | _ "github.com/denisenkom/go-mssqldb" 9 | _ "github.com/go-sql-driver/mysql" 10 | _ "github.com/lib/pq" 11 | _ "github.com/mattn/go-sqlite3" 12 | ) 13 | 14 | func main() { 15 | log.SetFlags(log.LstdFlags | log.Lshortfile) 16 | if e := cmd.Execute(); e != nil { 17 | log.Fatalln(e) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pb/81dd3b50-f343-11eb-8332-dfc4915441d6/forward/forward/forward.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package jsgenerate_webpc.forward.forward; 4 | option go_package = "github.com/powerpuffpenguin/webpc/protocol/forward/forward"; 5 | 6 | service Forward { 7 | // websocket /api/forward/v1/forward/:id 8 | rpc Connect (stream ConnectRequest) returns (stream ConnectResponse); 9 | } 10 | enum Event { 11 | EventUniversal = 0; 12 | Heart = 1; 13 | Connect = 2; 14 | Binary = 3; 15 | }; 16 | message ConnectRequest{ 17 | Event event = 1; 18 | 19 | bytes binary = 2; 20 | // connect 21 | string addr = 3; 22 | } 23 | message ConnectResponse{ 24 | Event event = 1; 25 | 26 | bytes binary = 2; 27 | } -------------------------------------------------------------------------------- /pb/81dd3b50-f343-11eb-8332-dfc4915441d6/forward/vnc/vnc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package jsgenerate_webpc.forward.vnc; 4 | option go_package = "github.com/powerpuffpenguin/webpc/protocol/forward/vnc"; 5 | 6 | service Vnc { 7 | // websocket /api/forward/v1/vnc/:id 8 | rpc Connect (stream ConnectRequest) returns (stream ConnectResponse); 9 | } 10 | enum Event { 11 | EventUniversal = 0; 12 | Heart = 1; 13 | Connect = 2; 14 | Binary = 3; 15 | }; 16 | message ConnectRequest{ 17 | Event event = 1; 18 | 19 | bytes binary = 2; 20 | } 21 | message ConnectResponse{ 22 | Event event = 1; 23 | 24 | bytes binary = 2; 25 | } -------------------------------------------------------------------------------- /script/conf.sh: -------------------------------------------------------------------------------- 1 | Target="webpc" 2 | Docker="king011/webpc" 3 | Dir=$(cd "$(dirname $BASH_SOURCE)/.." && pwd) 4 | Version="v1.3.1" 5 | View=1 6 | Platforms=( 7 | windows/amd64 8 | darwin/amd64 9 | linux/arm 10 | linux/amd64 11 | ) 12 | UUID="81dd3b50-f343-11eb-8332-dfc4915441d6" 13 | Protos=( 14 | system/system.proto 15 | session/session.proto 16 | user/user.proto 17 | logger/logger.proto 18 | slave/slave.proto 19 | group/group.proto 20 | 21 | forward/fs/fs.proto 22 | forward/logger/logger.proto 23 | forward/system/system.proto 24 | forward/shell/shell.proto 25 | forward/vnc/vnc.proto 26 | forward/forward/forward.proto 27 | ) 28 | -------------------------------------------------------------------------------- /sessionid/is.go: -------------------------------------------------------------------------------- 1 | package sessionid 2 | 3 | import ( 4 | "github.com/powerpuffpenguin/sessionstore/cryptoer" 5 | "google.golang.org/grpc/codes" 6 | "google.golang.org/grpc/status" 7 | ) 8 | 9 | func IsErrExpired(e error) bool { 10 | if e == nil { 11 | return false 12 | } 13 | if e == cryptoer.ErrExpired { 14 | return true 15 | } 16 | if se, ok := e.(interface { 17 | GRPCStatus() *status.Status 18 | }); ok { 19 | s := se.GRPCStatus() 20 | if s != nil { 21 | return s.Code() == codes.Unauthenticated && s.Message() == cryptoer.ErrExpired.Error() 22 | } 23 | } 24 | return false 25 | } 26 | -------------------------------------------------------------------------------- /sessionid/platforms.go: -------------------------------------------------------------------------------- 1 | package sessionid 2 | 3 | var platforms = []string{ 4 | `web`, 5 | `forward`, 6 | `socks5`, 7 | `android`, 8 | `ios`, 9 | `linux`, 10 | `windows`, 11 | `darwin`, 12 | } 13 | 14 | func Platforms() []string { 15 | return platforms 16 | } 17 | -------------------------------------------------------------------------------- /single/logger/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | func Init(filename string) { 4 | defaultFilesystem.onStart(filename) 5 | } 6 | -------------------------------------------------------------------------------- /slave/server/forward/auth.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/powerpuffpenguin/webpc/configure" 7 | "github.com/powerpuffpenguin/webpc/db" 8 | 9 | "google.golang.org/grpc/codes" 10 | ) 11 | 12 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 13 | if !configure.DefaultSystem().PortForward { 14 | return ctx, s.Error(codes.PermissionDenied, `port forward not enable`) 15 | } 16 | 17 | ctx, userdata, e := s.JSONUserdata(ctx) 18 | if e != nil { 19 | return ctx, e 20 | } else if userdata.AuthAny(db.Root, db.PortForward) { 21 | return ctx, nil 22 | } 23 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 24 | } 25 | -------------------------------------------------------------------------------- /slave/server/forward/init.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 5 | "github.com/powerpuffpenguin/webpc/configure" 6 | "github.com/powerpuffpenguin/webpc/logger" 7 | grpc_forward "github.com/powerpuffpenguin/webpc/protocol/forward/forward" 8 | "go.uber.org/zap" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_forward.RegisterForwardServer(srv, server{}) 16 | 17 | if ce := logger.Logger.Check(zap.InfoLevel, `port forward`); ce != nil { 18 | ce.Write( 19 | zap.Bool(`enable`, configure.DefaultSystem().PortForward), 20 | ) 21 | } 22 | } 23 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 24 | return nil 25 | } 26 | -------------------------------------------------------------------------------- /slave/server/forward/srv.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "github.com/powerpuffpenguin/webpc/m/helper" 5 | grpc_forward "github.com/powerpuffpenguin/webpc/protocol/forward/forward" 6 | "github.com/powerpuffpenguin/webpc/slave/server/forward/internal/connect" 7 | ) 8 | 9 | type server struct { 10 | grpc_forward.UnimplementedForwardServer 11 | helper.Helper 12 | } 13 | 14 | func (s server) Connect(server grpc_forward.Forward_ConnectServer) (e error) { 15 | w := connect.New(server) 16 | e = w.Serve() 17 | return 18 | } 19 | -------------------------------------------------------------------------------- /slave/server/fs/init.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "context" 5 | 6 | grpc_fs "github.com/powerpuffpenguin/webpc/protocol/forward/fs" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_fs.RegisterFSServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | return grpc_fs.RegisterFSHandler(context.Background(), gateway, cc) 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/fs/internal/upload/upload.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strconv" 7 | 8 | grpc_fs "github.com/powerpuffpenguin/webpc/protocol/forward/fs" 9 | "github.com/powerpuffpenguin/webpc/single/mount" 10 | ) 11 | 12 | var emptyUploadResponse grpc_fs.UploadResponse 13 | 14 | func Upload(m *mount.Mount, req *grpc_fs.UploadRequest) (resp *grpc_fs.UploadResponse, e error) { 15 | dir, name := filepath.Split(req.Path) 16 | dir = filepath.Join(dir, `.chunks_`+name) 17 | m.Mkdir(dir, 0775) 18 | path := filepath.Join(dir, strconv.FormatInt(int64(req.Chunk), 10)) 19 | f, e := m.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) 20 | if e != nil { 21 | return 22 | } 23 | _, e = f.Write(req.Data) 24 | f.Close() 25 | if e != nil { 26 | return 27 | } 28 | resp = &emptyUploadResponse 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /slave/server/logger/auth.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/powerpuffpenguin/webpc/db" 7 | 8 | "google.golang.org/grpc/codes" 9 | ) 10 | 11 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 12 | ctx, userdata, e := s.JSONUserdata(ctx) 13 | if e != nil { 14 | return ctx, e 15 | } else if userdata.AuthAny(db.Root) { 16 | return ctx, nil 17 | } 18 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/logger/init.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "context" 5 | 6 | grpc_logger "github.com/powerpuffpenguin/webpc/protocol/forward/logger" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_logger.RegisterLoggerServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | return grpc_logger.RegisterLoggerHandler(context.Background(), gateway, cc) 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/shell/auth.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/powerpuffpenguin/webpc/db" 7 | 8 | "google.golang.org/grpc/codes" 9 | ) 10 | 11 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 12 | ctx, userdata, e := s.JSONUserdata(ctx) 13 | if e != nil { 14 | return ctx, e 15 | } else if userdata.AuthAny(db.Root, db.Shell) { 16 | return ctx, nil 17 | } 18 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/shell/init.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 7 | grpc_shell "github.com/powerpuffpenguin/webpc/protocol/forward/shell" 8 | "github.com/powerpuffpenguin/webpc/slave/server/shell/internal/db" 9 | "github.com/powerpuffpenguin/webpc/slave/server/shell/internal/shell" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | type Module int 14 | 15 | func (Module) RegisterGRPC(srv *grpc.Server) { 16 | db.Init() 17 | shell.Init() 18 | 19 | grpc_shell.RegisterShellServer(srv, server{}) 20 | } 21 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 22 | return grpc_shell.RegisterShellHandler(context.Background(), gateway, cc) 23 | } 24 | -------------------------------------------------------------------------------- /slave/server/shell/internal/db/data.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | const ( 4 | tableName = `data_of_slave_shell` 5 | 6 | colID = `id` 7 | colUserName = `username` 8 | colName = `name` 9 | colFontSize = `fontSize` 10 | colFontFamily = `fontFamily` 11 | ) 12 | 13 | type DataOfSlaveShell struct { 14 | ID int64 `xorm:"pk 'id'"` 15 | UserName string `xorm:"index 'username' default('') "` 16 | Name string `xorm:"'name' default('') "` 17 | FontSize int32 `xorm:"'fontSize' default('') "` 18 | FontFamily string `xorm:"'fontFamily' default('') "` 19 | } 20 | 21 | func (DataOfSlaveShell) TableName() string { 22 | return tableName 23 | } 24 | -------------------------------------------------------------------------------- /slave/server/shell/internal/db/init.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "github.com/powerpuffpenguin/webpc/db/manipulator" 5 | "github.com/powerpuffpenguin/webpc/logger" 6 | 7 | "go.uber.org/zap" 8 | ) 9 | 10 | func Init() { 11 | manipulator.Engine().SetCacher(tableName, nil) 12 | 13 | e := doInit() 14 | if e != nil { 15 | logger.Logger.Panic(`init db error`, 16 | zap.Error(e), 17 | zap.String(`table`, tableName), 18 | ) 19 | return 20 | } 21 | } 22 | func doInit() (e error) { 23 | session, e := manipulator.Begin() 24 | if e != nil { 25 | return 26 | } 27 | defer session.Close() 28 | 29 | // sync 30 | bean := &DataOfSlaveShell{} 31 | e = manipulator.SyncTable(session, bean) 32 | if e != nil { 33 | return 34 | } 35 | e = session.Commit() 36 | return 37 | } 38 | -------------------------------------------------------------------------------- /slave/server/shell/internal/shell/init.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "github.com/powerpuffpenguin/webpc/configure" 5 | "github.com/powerpuffpenguin/webpc/logger" 6 | "go.uber.org/zap" 7 | ) 8 | 9 | func Init() { 10 | cnf := configure.DefaultSystem() 11 | command = cnf.Shell 12 | if ce := logger.Logger.Check(zap.InfoLevel, `shell`); ce != nil { 13 | ce.Write( 14 | zap.String("shell", command), 15 | ) 16 | } 17 | 18 | DefaultManager().restore() 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/system/init.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "context" 5 | 6 | grpc_system "github.com/powerpuffpenguin/webpc/protocol/forward/system" 7 | 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type Module int 13 | 14 | func (Module) RegisterGRPC(srv *grpc.Server) { 15 | grpc_system.RegisterSystemServer(srv, server{}) 16 | } 17 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 18 | return grpc_system.RegisterSystemHandler(context.Background(), gateway, cc) 19 | } 20 | -------------------------------------------------------------------------------- /slave/server/vnc/auth.go: -------------------------------------------------------------------------------- 1 | package vnc 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/powerpuffpenguin/webpc/db" 7 | "github.com/powerpuffpenguin/webpc/slave/server/vnc/internal/connect" 8 | 9 | "google.golang.org/grpc/codes" 10 | ) 11 | 12 | func (s server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) { 13 | if connect.VNC == `` { 14 | return ctx, s.Error(codes.PermissionDenied, `vnc not enable`) 15 | } 16 | 17 | ctx, userdata, e := s.JSONUserdata(ctx) 18 | if e != nil { 19 | return ctx, e 20 | } else if userdata.AuthAny(db.Root, db.VNC) { 21 | return ctx, nil 22 | } 23 | return ctx, s.Error(codes.PermissionDenied, `permission denied`) 24 | } 25 | -------------------------------------------------------------------------------- /slave/server/vnc/init.go: -------------------------------------------------------------------------------- 1 | package vnc 2 | 3 | import ( 4 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 5 | "github.com/powerpuffpenguin/webpc/configure" 6 | "github.com/powerpuffpenguin/webpc/logger" 7 | grpc_vnc "github.com/powerpuffpenguin/webpc/protocol/forward/vnc" 8 | "github.com/powerpuffpenguin/webpc/slave/server/vnc/internal/connect" 9 | "go.uber.org/zap" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | type Module int 14 | 15 | func (Module) RegisterGRPC(srv *grpc.Server) { 16 | grpc_vnc.RegisterVncServer(srv, server{}) 17 | 18 | vnc := configure.DefaultSystem().VNC 19 | connect.VNC = vnc 20 | if ce := logger.Logger.Check(zap.InfoLevel, `vnc`); ce != nil { 21 | ce.Write(zap.String(`connect`, vnc)) 22 | } 23 | } 24 | func (Module) RegisterGateway(gateway *runtime.ServeMux, cc *grpc.ClientConn) error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /slave/server/vnc/srv.go: -------------------------------------------------------------------------------- 1 | package vnc 2 | 3 | import ( 4 | "github.com/powerpuffpenguin/webpc/m/helper" 5 | grpc_vnc "github.com/powerpuffpenguin/webpc/protocol/forward/vnc" 6 | "github.com/powerpuffpenguin/webpc/slave/server/vnc/internal/connect" 7 | ) 8 | 9 | type server struct { 10 | grpc_vnc.UnimplementedVncServer 11 | helper.Helper 12 | } 13 | 14 | func (s server) Connect(server grpc_vnc.Vnc_ConnectServer) (e error) { 15 | w := connect.New(server) 16 | e = w.Serve() 17 | return 18 | } 19 | -------------------------------------------------------------------------------- /static/document/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/document/favicon-16x16.png -------------------------------------------------------------------------------- /static/document/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/document/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/favicon.ico -------------------------------------------------------------------------------- /static/public/noVNC/.eslintignore: -------------------------------------------------------------------------------- 1 | **/xtscancodes.js 2 | -------------------------------------------------------------------------------- /static/public/noVNC/.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question or discussion 4 | url: https://groups.google.com/forum/?fromgroups#!forum/novnc 5 | about: Ask a question or start a discussion 6 | -------------------------------------------------------------------------------- /static/public/noVNC/.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /static/public/noVNC/.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | eslint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: actions/setup-node@v3 11 | - run: npm update 12 | - run: npm run lint 13 | html: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: actions/setup-node@v3 18 | - run: npm update 19 | - run: git ls-tree --name-only -r HEAD | grep -E "[.](html|css)$" | xargs ./utils/validate 20 | -------------------------------------------------------------------------------- /static/public/noVNC/.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | strategy: 8 | matrix: 9 | os: 10 | - ubuntu-latest 11 | - windows-latest 12 | browser: 13 | - ChromeHeadless 14 | - FirefoxHeadless 15 | include: 16 | - os: macos-latest 17 | browser: Safari 18 | - os: windows-latest 19 | browser: EdgeHeadless 20 | fail-fast: false 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - uses: actions/checkout@v3 24 | - uses: actions/setup-node@v3 25 | - run: npm update 26 | - run: npm run test 27 | env: 28 | TEST_BROWSER_NAME: ${{ matrix.browser }} 29 | -------------------------------------------------------------------------------- /static/public/noVNC/.github/workflows/translate.yml: -------------------------------------------------------------------------------- 1 | name: Translate 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | translate: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: actions/setup-node@v3 11 | - run: npm update 12 | - run: sudo apt-get install gettext 13 | - run: make -C po update-pot 14 | - run: make -C po update-po 15 | - run: make -C po update-js 16 | -------------------------------------------------------------------------------- /static/public/noVNC/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.o 3 | tests/data_*.js 4 | utils/rebind.so 5 | utils/websockify 6 | /node_modules 7 | /build 8 | /lib 9 | recordings 10 | *.swp 11 | *~ 12 | noVNC-*.tgz 13 | -------------------------------------------------------------------------------- /static/public/noVNC/.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/.gitmodules -------------------------------------------------------------------------------- /static/public/noVNC/AUTHORS: -------------------------------------------------------------------------------- 1 | maintainers: 2 | - Samuel Mannehed for Cendio AB (@samhed) 3 | - Pierre Ossman for Cendio AB (@CendioOssman) 4 | maintainersEmeritus: 5 | - Joel Martin (@kanaka) 6 | - Solly Ross (@directxman12) 7 | - @astrand 8 | contributors: 9 | # There are a bunch of people that should be here. 10 | # If you want to be on this list, feel free send a PR 11 | # to add yourself. 12 | - jalf 13 | - NTT corp. 14 | -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-120.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-152.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-167.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-180.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-40.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-58.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-60.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-80.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc-ios-87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc-ios-87.png -------------------------------------------------------------------------------- /static/public/noVNC/app/images/icons/novnc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/images/icons/novnc.ico -------------------------------------------------------------------------------- /static/public/noVNC/app/locale/README: -------------------------------------------------------------------------------- 1 | DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES. 2 | -------------------------------------------------------------------------------- /static/public/noVNC/app/sounds/CREDITS: -------------------------------------------------------------------------------- 1 | bell 2 | Copyright: Dr. Richard Boulanger et al 3 | URL: http://www.archive.org/details/Berklee44v12 4 | License: CC-BY Attribution 3.0 Unported 5 | -------------------------------------------------------------------------------- /static/public/noVNC/app/sounds/bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/sounds/bell.mp3 -------------------------------------------------------------------------------- /static/public/noVNC/app/sounds/bell.oga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/sounds/bell.oga -------------------------------------------------------------------------------- /static/public/noVNC/app/styles/Orbitron700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/styles/Orbitron700.ttf -------------------------------------------------------------------------------- /static/public/noVNC/app/styles/Orbitron700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/app/styles/Orbitron700.woff -------------------------------------------------------------------------------- /static/public/noVNC/core/decoders/copyrect.js: -------------------------------------------------------------------------------- 1 | /* 2 | * noVNC: HTML5 VNC client 3 | * Copyright (C) 2019 The noVNC Authors 4 | * Licensed under MPL 2.0 (see LICENSE.txt) 5 | * 6 | * See README.md for usage and integration instructions. 7 | * 8 | */ 9 | 10 | export default class CopyRectDecoder { 11 | decodeRect(x, y, width, height, sock, display, depth) { 12 | if (sock.rQwait("COPYRECT", 4)) { 13 | return false; 14 | } 15 | 16 | let deltaX = sock.rQshift16(); 17 | let deltaY = sock.rQshift16(); 18 | 19 | if ((width === 0) || (height === 0)) { 20 | return true; 21 | } 22 | 23 | display.copyImage(deltaX, deltaY, x, y, width, height); 24 | 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /static/public/noVNC/core/decoders/tightpng.js: -------------------------------------------------------------------------------- 1 | /* 2 | * noVNC: HTML5 VNC client 3 | * Copyright (C) 2019 The noVNC Authors 4 | * Licensed under MPL 2.0 (see LICENSE.txt) 5 | * 6 | * See README.md for usage and integration instructions. 7 | * 8 | */ 9 | 10 | import TightDecoder from './tight.js'; 11 | 12 | export default class TightPNGDecoder extends TightDecoder { 13 | _pngRect(x, y, width, height, sock, display, depth) { 14 | let data = this._readData(sock); 15 | if (data === null) { 16 | return false; 17 | } 18 | 19 | display.imageRect(x, y, width, height, "image/png", data); 20 | 21 | return true; 22 | } 23 | 24 | _basicRect(ctl, x, y, width, height, sock, display, depth) { 25 | throw new Error("BasicCompression received in TightPNG rect"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /static/public/noVNC/core/util/int.js: -------------------------------------------------------------------------------- 1 | /* 2 | * noVNC: HTML5 VNC client 3 | * Copyright (C) 2020 The noVNC Authors 4 | * Licensed under MPL 2.0 (see LICENSE.txt) 5 | * 6 | * See README.md for usage and integration instructions. 7 | */ 8 | 9 | export function toUnsigned32bit(toConvert) { 10 | return toConvert >>> 0; 11 | } 12 | 13 | export function toSigned32bit(toConvert) { 14 | return toConvert | 0; 15 | } 16 | -------------------------------------------------------------------------------- /static/public/noVNC/core/util/strings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * noVNC: HTML5 VNC client 3 | * Copyright (C) 2019 The noVNC Authors 4 | * Licensed under MPL 2.0 (see LICENSE.txt) 5 | * 6 | * See README.md for usage and integration instructions. 7 | */ 8 | 9 | // Decode from UTF-8 10 | export function decodeUTF8(utf8string, allowLatin1=false) { 11 | try { 12 | return decodeURIComponent(escape(utf8string)); 13 | } catch (e) { 14 | if (e instanceof URIError) { 15 | if (allowLatin1) { 16 | // If we allow Latin1 we can ignore any decoding fails 17 | // and in these cases return the original string 18 | return utf8string; 19 | } 20 | } 21 | throw e; 22 | } 23 | } 24 | 25 | // Encode to UTF-8 26 | export function encodeUTF8(DOMString) { 27 | return unescape(encodeURIComponent(DOMString)); 28 | } 29 | -------------------------------------------------------------------------------- /static/public/noVNC/docs/flash_policy.txt: -------------------------------------------------------------------------------- 1 | Manual setup: 2 | 3 | DATA="echo \'\'" 4 | /usr/bin/socat -T 1 TCP-L:843,reuseaddr,fork,crlf SYSTEM:"$DATA" 5 | -------------------------------------------------------------------------------- /static/public/noVNC/docs/notes: -------------------------------------------------------------------------------- 1 | Rebuilding inflator.js 2 | 3 | - Download pako from npm 4 | - Install browserify using npm 5 | - browserify core/inflator.mod.js -o core/inflator.js -s Inflator 6 | -------------------------------------------------------------------------------- /static/public/noVNC/docs/rfbproto-3.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/docs/rfbproto-3.3.pdf -------------------------------------------------------------------------------- /static/public/noVNC/docs/rfbproto-3.7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/docs/rfbproto-3.7.pdf -------------------------------------------------------------------------------- /static/public/noVNC/docs/rfbproto-3.8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/noVNC/docs/rfbproto-3.8.pdf -------------------------------------------------------------------------------- /static/public/noVNC/po/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /static/public/noVNC/snap/hooks/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | snapctl restart novnc.novncsvc 4 | -------------------------------------------------------------------------------- /static/public/noVNC/tests/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "mocha": true 5 | }, 6 | "globals": { 7 | "chai": false, 8 | "sinon": false 9 | }, 10 | "rules": { 11 | "prefer-arrow-callback": 0, 12 | // Too many anonymous callbacks 13 | "func-names": "off", 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /static/public/noVNC/tests/test.int.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const expect = chai.expect; 3 | 4 | import { toUnsigned32bit, toSigned32bit } from '../core/util/int.js'; 5 | 6 | describe('Integer casting', function () { 7 | it('should cast unsigned to signed', function () { 8 | let expected = 4294967286; 9 | expect(toUnsigned32bit(-10)).to.equal(expected); 10 | }); 11 | 12 | it('should cast signed to unsigned', function () { 13 | let expected = -10; 14 | expect(toSigned32bit(4294967286)).to.equal(expected); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /static/public/noVNC/tests/vnc_playback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VNC Playback 5 | 6 | 7 | 8 | 9 | Iterations:   10 | Perftest:  11 | Realtime:   12 | 13 |   14 | 15 |

16 | 17 | Results:
18 | 19 | 20 |

21 | 22 |
23 |
Loading
24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /static/public/noVNC/utils/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true 4 | }, 5 | "rules": { 6 | "no-console": 0 7 | } 8 | } -------------------------------------------------------------------------------- /static/public/noVNC/utils/README.md: -------------------------------------------------------------------------------- 1 | ## WebSockets Proxy/Bridge 2 | 3 | Websockify has been forked out into its own project. `novnc_proxy` will 4 | automatically download it here if it is not already present and not 5 | installed as system-wide. 6 | 7 | For more detailed description and usage information please refer to 8 | the [websockify README](https://github.com/novnc/websockify/blob/master/README.md). 9 | 10 | The other versions of websockify (C, Node.js) and the associated test 11 | programs have been moved to 12 | [websockify](https://github.com/novnc/websockify). Websockify was 13 | formerly named wsproxy. 14 | 15 | -------------------------------------------------------------------------------- /static/public/noVNC/utils/b64-to-binary.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use MIME::Base64; 3 | 4 | for (<>) { 5 | unless (/^'([{}])(\d+)\1(.+?)',$/) { 6 | print; 7 | next; 8 | } 9 | 10 | my ($dir, $amt, $b64) = ($1, $2, $3); 11 | 12 | my $decoded = MIME::Base64::decode($b64) or die "Could not base64-decode line `$_`"; 13 | 14 | my $decoded_escaped = join "", map { "\\x$_" } unpack("(H2)*", $decoded); 15 | 16 | print "'${dir}${amt}${dir}${decoded_escaped}',\n"; 17 | } 18 | -------------------------------------------------------------------------------- /static/public/noVNC/utils/validate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | RET=0 6 | 7 | OUT=`mktemp` 8 | 9 | for fn in "$@"; do 10 | echo "Validating $fn..." 11 | echo 12 | 13 | case $fn in 14 | *.html) 15 | type="text/html" 16 | ;; 17 | *.css) 18 | type="text/css" 19 | ;; 20 | *) 21 | echo "Unknown format!" 22 | echo 23 | RET=1 24 | continue 25 | ;; 26 | esac 27 | 28 | curl --silent \ 29 | --header "Content-Type: ${type}; charset=utf-8" \ 30 | --data-binary @${fn} \ 31 | https://validator.w3.org/nu/?out=text > $OUT 32 | cat $OUT 33 | echo 34 | 35 | # We don't fail the check for warnings as some warnings are 36 | # not relevant for us, and we don't currently have a way to 37 | # ignore just those 38 | if grep -q -s -E "^Error:" $OUT; then 39 | RET=1 40 | fi 41 | done 42 | 43 | rm $OUT 44 | 45 | exit $RET 46 | -------------------------------------------------------------------------------- /static/public/noVNC/vendor/pako/README.md: -------------------------------------------------------------------------------- 1 | This is an ES6-modules-compatible version of 2 | https://github.com/nodeca/pako, based on pako version 1.0.3. 3 | 4 | It's more-or-less a direct translation of the original, with unused parts 5 | removed, and the dynamic support for non-typed arrays removed (since ES6 6 | modules don't work well with dynamic exports). 7 | -------------------------------------------------------------------------------- /static/public/noVNC/vendor/pako/lib/zlib/adler32.js: -------------------------------------------------------------------------------- 1 | // Note: adler32 takes 12% for level 0 and 2% for level 6. 2 | // It doesn't worth to make additional optimizationa as in original. 3 | // Small size is preferable. 4 | 5 | export default function adler32(adler, buf, len, pos) { 6 | var s1 = (adler & 0xffff) |0, 7 | s2 = ((adler >>> 16) & 0xffff) |0, 8 | n = 0; 9 | 10 | while (len !== 0) { 11 | // Set limit ~ twice less than 5552, to keep 12 | // s2 in 31-bits, because we force signed ints. 13 | // in other case %= will fail. 14 | n = len > 2000 ? 2000 : len; 15 | len -= n; 16 | 17 | do { 18 | s1 = (s1 + buf[pos++]) |0; 19 | s2 = (s2 + s1) |0; 20 | } while (--n); 21 | 22 | s1 %= 65521; 23 | s2 %= 65521; 24 | } 25 | 26 | return (s1 | (s2 << 16)) |0; 27 | } 28 | -------------------------------------------------------------------------------- /static/public/noVNC/vendor/pako/lib/zlib/messages.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 2: 'need dictionary', /* Z_NEED_DICT 2 */ 3 | 1: 'stream end', /* Z_STREAM_END 1 */ 4 | 0: '', /* Z_OK 0 */ 5 | '-1': 'file error', /* Z_ERRNO (-1) */ 6 | '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ 7 | '-3': 'data error', /* Z_DATA_ERROR (-3) */ 8 | '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ 9 | '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ 10 | '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ 11 | }; 12 | -------------------------------------------------------------------------------- /static/public/theme/color-deeppurple-amber.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | --theme-background: #fafafa; 3 | --theme-color:rgba(0,0,0,.87); 4 | --theme-color-primary: #673ab7; 5 | --theme-color-accent: #ffd740; 6 | --theme-color-warn: #f44336; 7 | } 8 | body{ 9 | background: var(--theme-background); 10 | color: var(--theme-color); 11 | font-family: Roboto,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif; 12 | margin: 0; 13 | } 14 | -------------------------------------------------------------------------------- /static/public/theme/color-indigo-pink.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | --theme-background: #fafafa; 3 | --theme-color:rgba(0,0,0,.87); 4 | --theme-color-primary: #3f51b5; 5 | --theme-color-accent: #ff4081; 6 | --theme-color-warn: #f44336; 7 | } 8 | body{ 9 | background: var(--theme-background); 10 | color: var(--theme-color); 11 | font-family: Roboto,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif; 12 | margin: 0; 13 | } -------------------------------------------------------------------------------- /static/public/theme/color-pink-bluegrey.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | --theme-background: #303030; 3 | --theme-color:#fff; 4 | --theme-color-primary: #c2185b; 5 | --theme-color-accent: #b0bec5; 6 | --theme-color-warn: #f44336; 7 | } 8 | body{ 9 | background: var(--theme-background); 10 | color: var(--theme-color); 11 | font-family: Roboto,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif; 12 | margin: 0; 13 | } -------------------------------------------------------------------------------- /static/public/theme/color-purple-green.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | --theme-background: #303030; 3 | --theme-color:#fff; 4 | --theme-color-primary: #7b1fa2; 5 | --theme-color-accent: #69f0ae; 6 | --theme-color-warn: #f44336; 7 | } 8 | body{ 9 | background: var(--theme-background); 10 | color: var(--theme-color); 11 | font-family: Roboto,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif; 12 | margin: 0; 13 | } 14 | -------------------------------------------------------------------------------- /static/public/theme/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/theme/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2 -------------------------------------------------------------------------------- /static/public/theme/icon.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url(flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } -------------------------------------------------------------------------------- /static/public/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /static/public/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /static/public/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /static/public/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /static/public/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /static/public/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /static/public/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /static/public/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /static/public/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /static/public/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /static/public/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /static/public/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/static/public/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /third_party/googleapis/README.grpc-gateway: -------------------------------------------------------------------------------- 1 | Google APIs 2 | ============ 3 | 4 | Project: Google APIs 5 | URL: https://github.com/google/googleapis 6 | Revision: 3544ab16c3342d790b00764251e348705991ea4b 7 | License: Apache License 2.0 8 | 9 | 10 | Imported Files 11 | --------------- 12 | 13 | - google/api/annotations.proto 14 | - google/api/http.proto 15 | - google/api/httpbody.proto 16 | 17 | 18 | Generated Files 19 | ---------------- 20 | 21 | They are generated from the .proto files by protoc-gen-go. 22 | - google/api/annotations.pb.go 23 | - google/api/http.pb.go 24 | -------------------------------------------------------------------------------- /utils/bytes.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | "unsafe" 7 | ) 8 | 9 | // BytesToString converts byte slice to string. 10 | func BytesToString(b []byte) string { 11 | return *(*string)(unsafe.Pointer(&b)) 12 | } 13 | 14 | // StringToBytes converts string to byte slice. 15 | func StringToBytes(s string) []byte { 16 | return *(*[]byte)(unsafe.Pointer( 17 | &struct { 18 | string 19 | Cap int 20 | }{s, len(s)}, 21 | )) 22 | } 23 | 24 | func MD5String(val string) (result string) { 25 | b := md5.Sum(StringToBytes(val)) 26 | return hex.EncodeToString(b[:]) 27 | } 28 | -------------------------------------------------------------------------------- /utils/match.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "regexp" 5 | ) 6 | 7 | var matchName = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9]+$`) 8 | var matchPassword = regexp.MustCompile(`^[a-f0-9]+$`) 9 | 10 | // MatchName if match user name return true 11 | func MatchName(val string) bool { 12 | if len(val) < 4 { 13 | return false 14 | } 15 | return matchName.MatchString(val) 16 | } 17 | 18 | // MatchPassword if match passsword name return true 19 | func MatchPassword(val string) bool { 20 | if len(val) != 32 { 21 | return false 22 | } 23 | return matchPassword.MatchString(val) 24 | } 25 | -------------------------------------------------------------------------------- /utils/match_test.go: -------------------------------------------------------------------------------- 1 | package utils_test 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/rand" 6 | "encoding/hex" 7 | "github.com/powerpuffpenguin/webpc/utils" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestName(t *testing.T) { 14 | assert.True(t, utils.MatchName(`a123`)) 15 | assert.False(t, utils.MatchName(`3123`)) 16 | assert.True(t, utils.MatchName(`A123A`)) 17 | assert.False(t, utils.MatchName(`A12`)) 18 | } 19 | func TestPassword(t *testing.T) { 20 | buf := make([]byte, 1024) 21 | for i := 0; i < 1000; i++ { 22 | rand.Read(buf) 23 | b := md5.Sum(buf) 24 | pwd := hex.EncodeToString(b[:]) 25 | assert.True(t, utils.MatchPassword(pwd)) 26 | } 27 | } -------------------------------------------------------------------------------- /utils/path.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "os/exec" 7 | "path/filepath" 8 | ) 9 | 10 | var basePath string 11 | 12 | // BasePath return executable file directory 13 | func BasePath() string { 14 | if basePath != `` { 15 | return basePath 16 | } 17 | filename, e := exec.LookPath(os.Args[0]) 18 | if e != nil { 19 | log.Fatalln(e) 20 | } 21 | 22 | filename, e = filepath.Abs(filename) 23 | if e != nil { 24 | log.Fatalln(e) 25 | } 26 | basePath = filepath.Dir(filename) 27 | return basePath 28 | } 29 | 30 | // Abs Use bashPath as the working directory to return the absolute path 31 | func Abs(bashPath, path string) string { 32 | if filepath.IsAbs(path) { 33 | path = filepath.Clean(path) 34 | } else { 35 | path = filepath.Clean(filepath.Join(bashPath, path)) 36 | } 37 | return path 38 | } 39 | -------------------------------------------------------------------------------- /version/platform.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | var Platform = fmt.Sprintf(`%v %v %v gin%v`, 11 | runtime.GOOS, runtime.GOARCH, runtime.Version(), 12 | gin.Version[1:], 13 | ) 14 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | var ( 4 | Version = `v1.2.8` 5 | Date = `` 6 | Commit = `` 7 | ) 8 | -------------------------------------------------------------------------------- /view/.angulardoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "repoId": "64248d86-1275-46e9-aa44-c9b5d7fde44b", 3 | "lastSync": 0 4 | } -------------------------------------------------------------------------------- /view/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /view/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | .angular -------------------------------------------------------------------------------- /view/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('view app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /view/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /view/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../out-tsc/e2e", 6 | "module": "commonjs", 7 | "target": "es2018", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /view/ngsw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/service-worker/config/schema.json", 3 | "index": "/index.html", 4 | "assetGroups": [ 5 | { 6 | "name": "app", 7 | "installMode": "prefetch", 8 | "resources": { 9 | "files": [ 10 | "/favicon.ico", 11 | "/index.html", 12 | "/manifest.webmanifest", 13 | "/*.css", 14 | "/*.js" 15 | ] 16 | } 17 | }, 18 | { 19 | "name": "assets", 20 | "installMode": "lazy", 21 | "updateMode": "prefetch", 22 | "resources": { 23 | "files": [ 24 | "/assets/**", 25 | "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)" 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /view/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | header{ 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | z-index: 2; 7 | } 8 | .main{ 9 | margin-top: 58px; 10 | } 11 | .fullscreen{ 12 | margin-top: 0px; 13 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/add/add.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/add/add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AddComponent } from './add.component'; 4 | 5 | describe('AddComponent', () => { 6 | let component: AddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/dialog/code/code.component.html: -------------------------------------------------------------------------------- 1 |

code of {{data.name}}

2 | 3 |
4 |
5 | Changing the code will make the device using the code unable to register, please confirm the operation! 6 |
7 |
8 | 10 | 12 | 13 |
14 |
-------------------------------------------------------------------------------- /view/src/app/app/dialog/code/code.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/code/code.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CodeComponent } from './code.component'; 4 | 5 | describe('CodeComponent', () => { 6 | let component: CodeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CodeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CodeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/dialog/delete/delete.component.html: -------------------------------------------------------------------------------- 1 |

delete {{data.name}}

2 | 3 |
4 | Once deleted, the data cannot be recovered. Please confirm the operation. 5 |
6 |
7 | 9 | 10 | 11 |
-------------------------------------------------------------------------------- /view/src/app/app/dialog/delete/delete.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/delete/delete.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DeleteComponent } from './delete.component'; 4 | 5 | describe('DeleteComponent', () => { 6 | let component: DeleteComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DeleteComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DeleteComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/dialog/edit/edit.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } 7 | .mat-checkbox{ 8 | margin-right: 8px; 9 | } 10 | .fill{ 11 | padding-bottom: 24px; 12 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/edit/edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditComponent } from './edit.component'; 4 | 5 | describe('EditComponent', () => { 6 | let component: EditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/dialog/group/group.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/app/dialog/group/group.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { GroupComponent } from './group.component'; 4 | 5 | describe('GroupComponent', () => { 6 | let component: GroupComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ GroupComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(GroupComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/home/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Welcome, you are using the webpc, please sign in first.

9 |
10 |
-------------------------------------------------------------------------------- /view/src/app/app/home/home.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/app/home/home.component.scss -------------------------------------------------------------------------------- /view/src/app/app/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | describe('HomeComponent', () => { 6 | let component: HomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ HomeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HomeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/app/query/query.component.scss: -------------------------------------------------------------------------------- 1 | .query{ 2 | padding-right: 16px; 3 | } 4 | table { 5 | width: 100%; 6 | } -------------------------------------------------------------------------------- /view/src/app/app/query/query.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { QueryComponent } from './query.component'; 4 | 5 | describe('QueryComponent', () => { 6 | let component: QueryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ QueryComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(QueryComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/content/about/about.component.scss: -------------------------------------------------------------------------------- 1 | pre{ 2 | white-space: pre-wrap; 3 | word-wrap: break-word; 4 | } 5 | .mat-card:not(:first-child){ 6 | margin-top: 8px; 7 | } -------------------------------------------------------------------------------- /view/src/app/content/about/about.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AboutComponent } from './about.component'; 4 | 5 | describe('AboutComponent', () => { 6 | let component: AboutComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AboutComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AboutComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/content/content-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { RootGuard } from '../core/guard/root.guard'; 4 | import { AboutComponent } from './about/about.component'; 5 | import { VersionComponent } from './version/version.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: 'about', 10 | component: AboutComponent, 11 | }, 12 | { 13 | path: 'version', 14 | component: VersionComponent, 15 | canActivate: [RootGuard], 16 | }, 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forChild(routes)], 21 | exports: [RouterModule] 22 | }) 23 | export class ContentRoutingModule { } 24 | -------------------------------------------------------------------------------- /view/src/app/content/content.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ContentRoutingModule } from './content-routing.module'; 5 | 6 | import { MatButtonModule } from '@angular/material/button'; 7 | import { MatIconModule } from '@angular/material/icon'; 8 | import { MatCardModule } from '@angular/material/card'; 9 | 10 | import { AboutComponent } from './about/about.component'; 11 | import { VersionComponent } from './version/version.component'; 12 | 13 | 14 | @NgModule({ 15 | declarations: [AboutComponent, VersionComponent], 16 | imports: [ 17 | CommonModule, 18 | MatButtonModule, MatIconModule, MatCardModule, 19 | ContentRoutingModule 20 | ] 21 | }) 22 | export class ContentModule { } 23 | -------------------------------------------------------------------------------- /view/src/app/content/version/version.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

angular {{VERSION.full}}

5 |
6 |

{{response.platform}}

7 |

{{response.version}}

8 |

{{response.commit}}

9 |

build at {{response.date}}

10 |

start at {{startAt}}, started {{started}}.

11 |
12 |
13 |
14 |
-------------------------------------------------------------------------------- /view/src/app/content/version/version.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/content/version/version.component.scss -------------------------------------------------------------------------------- /view/src/app/content/version/version.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { VersionComponent } from './version.component'; 4 | 5 | describe('VersionComponent', () => { 6 | let component: VersionComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ VersionComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(VersionComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | 5 | 6 | @NgModule({ 7 | declarations: [], 8 | imports: [ 9 | CommonModule 10 | ] 11 | }) 12 | export class CoreModule { } 13 | -------------------------------------------------------------------------------- /view/src/app/core/group/group.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { GroupService } from './group.service'; 4 | 5 | describe('GroupService', () => { 6 | let service: GroupService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(GroupService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/group/keys.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { KeysService } from './keys.service'; 4 | 5 | describe('KeysService', () => { 6 | let service: KeysService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(KeysService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/guard/access.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AccessGuard } from './access.guard'; 4 | 5 | describe('AccessGuard', () => { 6 | let guard: AccessGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(AccessGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/guard/fs.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { FsGuard } from './fs.guard'; 4 | 5 | describe('FsGuard', () => { 6 | let guard: FsGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(FsGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/guard/root.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { RootGuard } from './root.guard'; 4 | 5 | describe('RootGuard', () => { 6 | let guard: RootGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(RootGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/guard/shell.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ShellGuard } from './shell.guard'; 4 | 5 | describe('ShellGuard', () => { 6 | let guard: ShellGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(ShellGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/i18n/i18n.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { I18nService } from './i18n.service'; 4 | 5 | describe('I18nService', () => { 6 | let service: I18nService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(I18nService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/interceptor/header.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { HeaderService } from './header.service'; 4 | 5 | describe('HeaderService', () => { 6 | let service: HeaderService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(HeaderService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/interceptor/upgraded.ts: -------------------------------------------------------------------------------- 1 | import { BehaviorSubject, Observable } from "rxjs" 2 | 3 | export class Upgraded { 4 | static readonly instance = new Upgraded() 5 | private constructor() { 6 | } 7 | private version_ = new BehaviorSubject('') 8 | get versionObservable(): Observable { 9 | return this.version_ 10 | } 11 | nextVersion(version: string) { 12 | if (this.version_.value != version) { 13 | this.version_.next(version) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /view/src/app/core/navigation/navigation.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { NavigationService } from './navigation.service'; 4 | 5 | describe('NavigationService', () => { 6 | let service: NavigationService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(NavigationService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/session/session.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { SessionService } from './session.service'; 4 | 5 | describe('SessionService', () => { 6 | let service: SessionService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(SessionService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/settings/settings.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { SettingsService } from './settings.service'; 4 | 5 | describe('SettingsService', () => { 6 | let service: SettingsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(SettingsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/toaster.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ToasterService } from './toaster.service'; 4 | 5 | describe('ToasterService', () => { 6 | let service: ToasterService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(ToasterService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/core/utils/md5.ts: -------------------------------------------------------------------------------- 1 | import { hash } from 'spark-md5' 2 | export function md5String(message: string): string { 3 | return hash(message) 4 | } -------------------------------------------------------------------------------- /view/src/app/core/utils/promise.ts: -------------------------------------------------------------------------------- 1 | export function isPromise(obj: any): obj is Promise { 2 | return !!obj && 3 | (typeof obj === 'object' || typeof obj === 'function') && 4 | typeof obj.then === 'function' 5 | } -------------------------------------------------------------------------------- /view/src/app/dev/animations/animations.component.html: -------------------------------------------------------------------------------- 1 |

animations works!

2 | -------------------------------------------------------------------------------- /view/src/app/dev/animations/animations.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/dev/animations/animations.component.scss -------------------------------------------------------------------------------- /view/src/app/dev/animations/animations.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AnimationsComponent } from './animations.component'; 4 | 5 | describe('AnimationsComponent', () => { 6 | let component: AnimationsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AnimationsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AnimationsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/dev/animations/animations.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-animations', 5 | templateUrl: './animations.component.html', 6 | styleUrls: ['./animations.component.scss'] 7 | }) 8 | export class AnimationsComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /view/src/app/dev/dev-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { AnimationsComponent } from './animations/animations.component'; 4 | import { IndexComponent } from './index/index.component'; 5 | import { ToasterComponent } from './toaster/toaster.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | component: IndexComponent, 11 | }, 12 | { 13 | path: 'toaster', 14 | component: ToasterComponent, 15 | }, 16 | { 17 | path: 'animations', 18 | component: AnimationsComponent, 19 | } 20 | ]; 21 | 22 | @NgModule({ 23 | imports: [RouterModule.forChild(routes)], 24 | exports: [RouterModule] 25 | }) 26 | export class DevRoutingModule { } 27 | -------------------------------------------------------------------------------- /view/src/app/dev/index/index.component.html: -------------------------------------------------------------------------------- 1 |

2 | toaster 3 | animations 4 |

-------------------------------------------------------------------------------- /view/src/app/dev/index/index.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/dev/index/index.component.scss -------------------------------------------------------------------------------- /view/src/app/dev/index/index.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { IndexComponent } from './index.component'; 4 | 5 | describe('IndexComponent', () => { 6 | let component: IndexComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ IndexComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(IndexComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/dev/index/index.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-index', 5 | templateUrl: './index.component.html', 6 | styleUrls: ['./index.component.scss'] 7 | }) 8 | export class IndexComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /view/src/app/dev/toaster/toaster.component.scss: -------------------------------------------------------------------------------- 1 | .mat-checkbox:not(:first-child){ 2 | margin-left: 8px; 3 | } -------------------------------------------------------------------------------- /view/src/app/dev/toaster/toaster.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ToasterComponent } from './toaster.component'; 4 | 5 | describe('ToasterComponent', () => { 6 | let component: ToasterComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ToasterComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ToasterComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/dev/toaster/toaster.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ToasterService, ToastType } from 'src/app/core/toaster.service'; 3 | 4 | @Component({ 5 | selector: 'app-toaster', 6 | templateUrl: './toaster.component.html', 7 | styleUrls: ['./toaster.component.scss'] 8 | }) 9 | export class ToasterComponent implements OnInit { 10 | title = false 11 | type: ToastType = 'success' 12 | constructor(private readonly toasterService: ToasterService) { } 13 | 14 | ngOnInit(): void { 15 | } 16 | 17 | onSubmit() { 18 | let title: string | undefined 19 | if (this.title) { 20 | title = this.type 21 | } 22 | this.toasterService.pop(this.type, title, `${this.title}`) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/compress/compress.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-form-view{ 2 | padding-bottom: 25px; 3 | } 4 | .mat-radio-button ~ .mat-radio-button { 5 | margin-left: 16px; 6 | } 7 | .mat-spinner{ 8 | display: inline-block; 9 | margin-left: 8px; 10 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/compress/compress.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CompressComponent } from './compress.component'; 4 | 5 | describe('CompressComponent', () => { 6 | let component: CompressComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CompressComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CompressComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/copy/copy.component.html: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | Copy File 5 | 6 | 7 | Move File 8 | 9 | 10 |

11 |
12 |
{{progress}}
13 |
14 |
15 | 16 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/copy/copy.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/copy/copy.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CopyComponent } from './copy.component'; 4 | 5 | describe('CopyComponent', () => { 6 | let component: CopyComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CopyComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CopyComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists-choice/exists-choice.component.html: -------------------------------------------------------------------------------- 1 |

2 | File conflict 3 |

4 | 5 |
6 |
7 | Replace file 8 | 「{{filename}}」 9 |
10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists-choice/exists-choice.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/dialog/exists-choice/exists-choice.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists-choice/exists-choice.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExistsChoiceComponent } from './exists-choice.component'; 4 | 5 | describe('ExistsChoiceComponent', () => { 6 | let component: ExistsChoiceComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ExistsChoiceComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExistsChoiceComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists/exists.component.html: -------------------------------------------------------------------------------- 1 |

2 | File conflict 3 |

4 | 5 |
6 |
7 | Replace file 8 | 「{{filename}}」 9 |
10 |
11 |
12 | 13 | 14 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists/exists.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/dialog/exists/exists.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists/exists.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExistsComponent } from './exists.component'; 4 | 5 | describe('ExistsComponent', () => { 6 | let component: ExistsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ExistsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExistsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/exists/exists.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Inject } from '@angular/core'; 2 | import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; 3 | 4 | @Component({ 5 | selector: 'app-exists', 6 | templateUrl: './exists.component.html', 7 | styleUrls: ['./exists.component.scss'] 8 | }) 9 | export class ExistsComponent implements OnInit { 10 | 11 | constructor( 12 | private matDialogRef: MatDialogRef, 13 | @Inject(MAT_DIALOG_DATA) public filename: string,) { } 14 | 15 | ngOnInit(): void { 16 | } 17 | onSure() { 18 | this.matDialogRef.close(true) 19 | } 20 | onClose() { 21 | this.matDialogRef.close() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/new-file/new-file.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/new-file/new-file.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NewFileComponent } from './new-file.component'; 4 | 5 | describe('NewFileComponent', () => { 6 | let component: NewFileComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NewFileComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NewFileComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/new-folder/new-folder.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/new-folder/new-folder.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NewFolderComponent } from './new-folder.component'; 4 | 5 | describe('NewFolderComponent', () => { 6 | let component: NewFolderComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NewFolderComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NewFolderComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/property/property.component.html: -------------------------------------------------------------------------------- 1 |

2 | Property 3 |

4 |
5 | 6 | 7 | {{node.icon}} 8 |
{{node.name}}
9 |
{{node.modeString}} {{node.sizeString}}
10 |
11 |
12 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/property/property.component.scss: -------------------------------------------------------------------------------- 1 | mat-icon{ 2 | font-size: 36px; 3 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/property/property.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PropertyComponent } from './property.component'; 4 | 5 | describe('PropertyComponent', () => { 6 | let component: PropertyComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ PropertyComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PropertyComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/property/property.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Inject } from '@angular/core'; 2 | import { MAT_DIALOG_DATA } from '@angular/material/dialog'; 3 | import { FileInfo } from '../../fs'; 4 | @Component({ 5 | selector: 'app-property', 6 | templateUrl: './property.component.html', 7 | styleUrls: ['./property.component.scss'] 8 | }) 9 | export class PropertyComponent implements OnInit { 10 | 11 | constructor(@Inject(MAT_DIALOG_DATA) public source: Array, 12 | ) { 13 | } 14 | ngOnInit(): void { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/remove/remove.component.html: -------------------------------------------------------------------------------- 1 |

2 | Delete 3 | 4 | 5 | 6 |

7 |
8 | 9 | 10 | {{node.icon}} 11 |
{{node.name}}
12 |
{{node.modeString}} {{node.size}}
13 |
14 |
15 |
16 |
17 | 18 | 19 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/remove/remove.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/remove/remove.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RemoveComponent } from './remove.component'; 4 | 5 | describe('RemoveComponent', () => { 6 | let component: RemoveComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ RemoveComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RemoveComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/rename/rename.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/rename/rename.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RenameComponent } from './rename.component'; 4 | 5 | describe('RenameComponent', () => { 6 | let component: RenameComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ RenameComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RenameComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/uncompress/uncompress.component.html: -------------------------------------------------------------------------------- 1 |

2 | Uncompress 3 | 4 |

5 | 6 |
7 |
8 | {{target.source.name}} 9 |
10 |
{{progress}}
11 |
12 |
13 | 14 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/uncompress/uncompress.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/uncompress/uncompress.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UncompressComponent } from './uncompress.component'; 4 | 5 | describe('UncompressComponent', () => { 6 | let component: UncompressComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UncompressComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UncompressComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/upload/upload.component.scss: -------------------------------------------------------------------------------- 1 | .drop-zone { 2 | border: dotted 3px lightgray; 3 | padding: 8px; 4 | } 5 | .drop-zone-over { 6 | border: dotted 3px green; 7 | padding: 8px; 8 | } 9 | .mat-spinner{ 10 | display: inline-block; 11 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/dialog/upload/upload.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UploadComponent } from './upload.component'; 4 | 5 | describe('UploadComponent', () => { 6 | let component: UploadComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UploadComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UploadComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/file/file.component.html: -------------------------------------------------------------------------------- 1 |
2 | {{icon}} 3 |
4 | {{source.name}} 5 |
6 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/file/file.component.scss: -------------------------------------------------------------------------------- 1 | .mat-icon{ 2 | font-size: 36px; 3 | text-align: center; 4 | width: 100%; 5 | user-select: none; 6 | } 7 | 8 | .wrapper{ 9 | display: inline-block; 10 | width: 94px; 11 | cursor: pointer; 12 | 13 | -moz-user-select: none; 14 | -webkit-user-select: none; 15 | } 16 | .content{ 17 | width: 100%; 18 | height: 28px; 19 | 20 | text-overflow: ellipsis; 21 | -ms-text-overflow: ellipsis; 22 | -o-text-overflow: ellipsis; 23 | overflow:hidden; 24 | white-space: nowrap; 25 | text-align: center; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/file/file.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { FileComponent } from './file.component'; 4 | 5 | describe('FileComponent', () => { 6 | let component: FileComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ FileComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(FileComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/list/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/list/list.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/list/list.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/list/list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ListComponent } from './list.component'; 4 | 5 | describe('ListComponent', () => { 6 | let component: ListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ListComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/manager/manager.component.scss: -------------------------------------------------------------------------------- 1 | .rectangle{ 2 | background: yellowgreen; 3 | opacity: 0.5; 4 | position: fixed; 5 | } 6 | 7 | .footer{ 8 | position: fixed; 9 | bottom: 0; 10 | right: 0; 11 | left: 0; 12 | box-shadow: 0 2px 5px 0 rgba(0,0,0,.3); 13 | z-index: 10; 14 | } 15 | 16 | 17 | .actionMenu{ 18 | position: fixed; 19 | } 20 | 21 | .mat-icon{ 22 | font-size: 24px; 23 | } 24 | 25 | .view{ 26 | min-height: calc(100vh - 270px); 27 | } 28 | .menu{ 29 | margin-right: 14px; 30 | } 31 | .fs-path{ 32 | display: inline-block; 33 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/manager/manager.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ManagerComponent } from './manager.component'; 4 | 5 | describe('ManagerComponent', () => { 6 | let component: ManagerComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ManagerComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ManagerComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/navigation/navigation.component.html: -------------------------------------------------------------------------------- 1 | 2 | folder_special 3 | Filesystem management 4 | 5 | 6 | 7 | folder_special 8 | {{root}} 9 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/navigation/navigation.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/navigation/navigation.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/navigation/navigation.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NavigationComponent } from './navigation.component'; 4 | 5 | describe('NavigationComponent', () => { 6 | let component: NavigationComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NavigationComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NavigationComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/navigation/navigation.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'fs-navigation', 5 | templateUrl: './navigation.component.html', 6 | styleUrls: ['./navigation.component.scss'] 7 | }) 8 | export class NavigationComponent implements OnInit { 9 | @Input() 10 | target = '' 11 | 12 | @Input() 13 | root = '' 14 | constructor() { } 15 | 16 | ngOnInit(): void { 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/path/path.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/path/path.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/path/path.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PathComponent } from './path.component'; 4 | 5 | describe('PathComponent', () => { 6 | let component: PathComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ PathComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PathComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/plugins/movie/movie.component.scss: -------------------------------------------------------------------------------- 1 | .videoview{ 2 | display: flex; 3 | justify-content: center; 4 | } 5 | video{ 6 | max-width: 100%; 7 | } 8 | .btns{ 9 | padding-right: 8px; 10 | padding-bottom: 8px; 11 | } 12 | a{ 13 | margin-top: 8px; 14 | margin-left: 8px; 15 | } 16 | ::cue { 17 | background: none; 18 | color: #fff; 19 | text-shadow: 0 1px #000, 1px 0 #000, -1px 0 #000, 0 -1px #000; 20 | 21 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/plugins/movie/movie.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { MovieComponent } from './movie.component'; 4 | 5 | describe('MovieComponent', () => { 6 | let component: MovieComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ MovieComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(MovieComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/root/root.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-fs/root/root.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-fs/root/root.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RootComponent } from './root.component'; 4 | 5 | describe('RootComponent', () => { 6 | let component: RootComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ RootComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RootComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/audio/audio.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | Audio View 5 | {{filepath}} 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/view/audio/audio.component.scss: -------------------------------------------------------------------------------- 1 | audio{ 2 | width: 100%; 3 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/audio/audio.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AudioComponent } from './audio.component'; 4 | 5 | describe('AudioComponent', () => { 6 | let component: AudioComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AudioComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AudioComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/image/image.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | Image View 5 | {{filepath}} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
-------------------------------------------------------------------------------- /view/src/app/forward-fs/view/image/image.component.scss: -------------------------------------------------------------------------------- 1 | img{ 2 | max-width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/image/image.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ImageComponent } from './image.component'; 4 | 5 | describe('ImageComponent', () => { 6 | let component: ImageComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ImageComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ImageComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/text/text.component.scss: -------------------------------------------------------------------------------- 1 | .mat-form-field{ 2 | width: 100%; 3 | margin-top: 12px; 4 | } 5 | .mat-spinner{ 6 | display: inline-block; 7 | margin-left: 8px; 8 | } 9 | pre{ 10 | border-radius: 8px; 11 | padding: 6px 8px 6px 8px; 12 | background: var(--theme-background); 13 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/text/text.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TextComponent } from './text.component'; 4 | 5 | describe('TextComponent', () => { 6 | let component: TextComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ TextComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(TextComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/text/text.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { TextGuard } from './text.guard'; 4 | 5 | describe('TextGuard', () => { 6 | let guard: TextGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(TextGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/text/text.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 3 | import { Observable } from 'rxjs'; 4 | import { TextComponent } from './text.component' 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class TextGuard implements CanDeactivate { 10 | constructor() { } 11 | 12 | canDeactivate( 13 | component: TextComponent, 14 | currentRoute: ActivatedRouteSnapshot, 15 | currentState: RouterStateSnapshot, 16 | nextState: RouterStateSnapshot 17 | ): Observable | Promise | boolean { 18 | return component.canDeactivate() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/video/video.component.scss: -------------------------------------------------------------------------------- 1 | video{ 2 | max-width: 100%; 3 | } -------------------------------------------------------------------------------- /view/src/app/forward-fs/view/video/video.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { VideoComponent } from './video.component'; 4 | 5 | describe('VideoComponent', () => { 6 | let component: VideoComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ VideoComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(VideoComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-logger/attach/attach.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | Receive log 6 |
7 | 8 | 9 |
10 |
11 |
-------------------------------------------------------------------------------- /view/src/app/forward-logger/attach/attach.component.scss: -------------------------------------------------------------------------------- 1 | .view{ 2 | margin-top: 8px; 3 | // background-color: red; 4 | height: calc(100vh - 370px); 5 | height: calc(var(--vh, 1vh) * 100 - 370px); 6 | min-height: 100px; 7 | } 8 | .left{ 9 | margin-left: 12px; 10 | } -------------------------------------------------------------------------------- /view/src/app/forward-logger/attach/attach.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AttachComponent } from './attach.component'; 4 | 5 | describe('AttachComponent', () => { 6 | let component: AttachComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AttachComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AttachComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-logger/download/download.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-logger/download/download.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-logger/download/download.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DownloadComponent } from './download.component'; 4 | 5 | describe('DownloadComponent', () => { 6 | let component: DownloadComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DownloadComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DownloadComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-logger/forward-logger-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { DownloadComponent } from './download/download.component'; 4 | import { ViewComponent } from './view/view.component'; 5 | const routes: Routes = [ 6 | { 7 | path: 'view/:id', 8 | component: ViewComponent, 9 | }, 10 | { 11 | path: 'download/:id', 12 | component: DownloadComponent, 13 | } 14 | ]; 15 | 16 | @NgModule({ 17 | imports: [RouterModule.forChild(routes)], 18 | exports: [RouterModule] 19 | }) 20 | export class ForwardLoggerRoutingModule { } 21 | -------------------------------------------------------------------------------- /view/src/app/forward-logger/view/view.component.scss: -------------------------------------------------------------------------------- 1 | .mat-card-content .mat-stroked-button{ 2 | margin-left: 12px; 3 | } 4 | .left{ 5 | margin-left: 12px; 6 | } 7 | .mat-icon-button{ 8 | margin-top: -8px; 9 | } -------------------------------------------------------------------------------- /view/src/app/forward-logger/view/view.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ViewComponent } from './view.component'; 4 | 5 | describe('ViewComponent', () => { 6 | let component: ViewComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ViewComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ViewComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/delete/delete.component.html: -------------------------------------------------------------------------------- 1 |

delete {{data.name}}

2 | 3 |
4 | Once deleted, the data cannot be recovered. Please confirm the operation. 5 |
6 |
7 | 8 | 10 | 11 |
-------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/delete/delete.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/delete/delete.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DeleteComponent } from './delete.component'; 4 | 5 | describe('DeleteComponent', () => { 6 | let component: DeleteComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DeleteComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DeleteComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/edit/edit.component.scss: -------------------------------------------------------------------------------- 1 | .mat-spinner{ 2 | display: inline-block; 3 | margin-left: 8px; 4 | } 5 | .dialog-content{ 6 | max-width: 600px; 7 | } -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/edit/edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditComponent } from './edit.component'; 4 | 5 | describe('EditComponent', () => { 6 | let component: EditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/settings/settings.component.scss: -------------------------------------------------------------------------------- 1 | .setbtn{ 2 | margin-left: 8px; 3 | margin-right: 8px; 4 | } -------------------------------------------------------------------------------- /view/src/app/forward-shell/dialog/settings/settings.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SettingsComponent } from './settings.component'; 4 | 5 | describe('SettingsComponent', () => { 6 | let component: SettingsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SettingsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SettingsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/forward-shell-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { ListComponent } from './list/list.component'; 4 | import { ViewComponent } from './view/view.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: ':id', 9 | component: ListComponent, 10 | }, 11 | { 12 | path: ':id/:shellid', 13 | component: ViewComponent, 14 | }, 15 | ]; 16 | @NgModule({ 17 | imports: [RouterModule.forChild(routes)], 18 | exports: [RouterModule] 19 | }) 20 | export class ForwardShellRoutingModule { } 21 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/list/list.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward-shell/list/list.component.scss -------------------------------------------------------------------------------- /view/src/app/forward-shell/list/list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ListComponent } from './list.component'; 4 | 5 | describe('ListComponent', () => { 6 | let component: ListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ListComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/view/view.component.scss: -------------------------------------------------------------------------------- 1 | .shell{ 2 | height: calc(100vh - 225px); 3 | height: calc(var(--vh, 1vh) * 100 - 225px); 4 | min-height: 100px; 5 | } 6 | .fullview{ 7 | height: calc(100vh - 80px); 8 | height: calc(var(--vh, 1vh) * 100 - 80px); 9 | min-height: 100px; 10 | } 11 | .mat-spinner{ 12 | display: inline-block; 13 | margin-left: 8px; 14 | } 15 | 16 | .footer{ 17 | position: fixed; 18 | bottom: 0; 19 | right: 0; 20 | left: 0; 21 | box-shadow: 0 2px 5px 0 rgba(0,0,0,.3); 22 | z-index: 10; 23 | } 24 | .fill{ 25 | height: 64px; 26 | } 27 | -------------------------------------------------------------------------------- /view/src/app/forward-shell/view/view.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ViewComponent } from './view.component'; 4 | 5 | describe('ViewComponent', () => { 6 | let component: ViewComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ViewComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ViewComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward/home/home.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward/home/home.component.scss -------------------------------------------------------------------------------- /view/src/app/forward/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | describe('HomeComponent', () => { 6 | let component: HomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ HomeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HomeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/forward/shared/shared.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Shared 13 | 14 | 15 | 16 | 17 | folder_special 18 |

{{node}}

19 |
20 |
21 |
22 |
23 |
-------------------------------------------------------------------------------- /view/src/app/forward/shared/shared.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/forward/shared/shared.component.scss -------------------------------------------------------------------------------- /view/src/app/forward/shared/shared.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SharedComponent } from './shared.component'; 4 | 5 | describe('SharedComponent', () => { 6 | let component: SharedComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SharedComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SharedComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/dialog/add/add.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } 7 | -------------------------------------------------------------------------------- /view/src/app/group/dialog/add/add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AddComponent } from './add.component'; 4 | 5 | describe('AddComponent', () => { 6 | let component: AddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/dialog/delete/delete.component.html: -------------------------------------------------------------------------------- 1 |

delete {{data.name}}

2 | 3 |
4 | Once deleted, the data cannot be recovered. Please confirm the operation. 5 |
6 |
7 | 9 | 10 | 11 |
-------------------------------------------------------------------------------- /view/src/app/group/dialog/delete/delete.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/group/dialog/delete/delete.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DeleteComponent } from './delete.component'; 4 | 5 | describe('DeleteComponent', () => { 6 | let component: DeleteComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DeleteComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DeleteComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/dialog/edit/edit.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/group/dialog/edit/edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditComponent } from './edit.component'; 4 | 5 | describe('EditComponent', () => { 6 | let component: EditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/dialog/select/select.component.html: -------------------------------------------------------------------------------- 1 |

move {{data.name}} to

2 |
3 | 4 |
5 |
6 | 8 | 9 | 10 |
-------------------------------------------------------------------------------- /view/src/app/group/dialog/select/select.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/group/dialog/select/select.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SelectComponent } from './select.component'; 4 | 5 | describe('SelectComponent', () => { 6 | let component: SelectComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SelectComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SelectComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/group-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { ListComponent } from './list/list.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: ListComponent, 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class GroupRoutingModule { } 17 | -------------------------------------------------------------------------------- /view/src/app/group/list/list.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/group/list/list.component.scss -------------------------------------------------------------------------------- /view/src/app/group/list/list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ListComponent } from './list.component'; 4 | 5 | describe('ListComponent', () => { 6 | let component: ListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ListComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/group/list/node/node.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/group/list/node/node.component.scss -------------------------------------------------------------------------------- /view/src/app/group/list/node/node.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NodeComponent } from './node.component'; 4 | 5 | describe('NodeComponent', () => { 6 | let component: NodeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NodeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NodeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/logger/attach/attach.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | Receive log 6 |
7 | 8 | 9 |
10 |
11 |
-------------------------------------------------------------------------------- /view/src/app/logger/attach/attach.component.scss: -------------------------------------------------------------------------------- 1 | .view{ 2 | margin-top: 8px; 3 | // background-color: red; 4 | height: calc(100vh - 370px); 5 | height: calc(var(--vh, 1vh) * 100 - 370px); 6 | min-height: 100px; 7 | } 8 | .left{ 9 | margin-left: 12px; 10 | } -------------------------------------------------------------------------------- /view/src/app/logger/attach/attach.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AttachComponent } from './attach.component'; 4 | 5 | describe('AttachComponent', () => { 6 | let component: AttachComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AttachComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AttachComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/logger/download/download.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/logger/download/download.component.scss -------------------------------------------------------------------------------- /view/src/app/logger/download/download.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DownloadComponent } from './download.component'; 4 | 5 | describe('DownloadComponent', () => { 6 | let component: DownloadComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DownloadComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DownloadComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/logger/logger-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { DownloadComponent } from './download/download.component'; 4 | import { ViewComponent } from './view/view.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: ViewComponent, 10 | }, 11 | { 12 | path: 'download', 13 | component: DownloadComponent, 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule] 20 | }) 21 | export class LoggerRoutingModule { } 22 | -------------------------------------------------------------------------------- /view/src/app/logger/view/view.component.scss: -------------------------------------------------------------------------------- 1 | .mat-card-content .mat-stroked-button{ 2 | margin-left: 12px; 3 | } 4 | .left{ 5 | margin-left: 12px; 6 | } 7 | .mat-icon-button{ 8 | margin-top: -8px; 9 | } -------------------------------------------------------------------------------- /view/src/app/logger/view/view.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ViewComponent } from './view.component'; 4 | 5 | describe('ViewComponent', () => { 6 | let component: ViewComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ViewComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ViewComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view", 3 | "private": true, 4 | "description_1": "This is a special package.json file that is not used by package managers.", 5 | "description_2": "It is used to tell the tools and bundlers whether the code under this directory is free of code with non-local side-effect. Any code that does have non-local side-effects can't be well optimized (tree-shaken) and will result in unnecessary increased payload size.", 6 | "description_3": "It should be safe to set this option to 'false' for new applications, but existing code bases could be broken when built with the production config if the application code does contain non-local side-effects that the application depends on.", 7 | "description_4": "To learn more about this file see: https://angular.io/config/app-package-json.", 8 | "sideEffects": false 9 | } 10 | -------------------------------------------------------------------------------- /view/src/app/shared/load-view/load-view.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

connecting to server, please wait...

5 |
6 | 7 | 8 | 9 | Error 10 | 11 | 12 |
13 | {{err.id}} -> {{err.err}} 14 |
15 |
16 | 17 | 18 | 19 |
20 |
-------------------------------------------------------------------------------- /view/src/app/shared/load-view/load-view.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/shared/load-view/load-view.component.scss -------------------------------------------------------------------------------- /view/src/app/shared/load-view/load-view.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoadViewComponent } from './load-view.component'; 4 | 5 | describe('LoadViewComponent', () => { 6 | let component: LoadViewComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ LoadViewComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoadViewComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/load-view/load-view.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; 2 | export interface LoadError { 3 | id: string 4 | err: any 5 | } 6 | @Component({ 7 | selector: 'shared-load-view', 8 | templateUrl: './load-view.component.html', 9 | styleUrls: ['./load-view.component.scss'] 10 | }) 11 | export class LoadViewComponent implements OnInit { 12 | @Input() 13 | hasErr = false 14 | @Input() 15 | errs: Array = [] 16 | @Output() 17 | valChange = new EventEmitter() 18 | constructor() { } 19 | ngOnInit(): void { 20 | } 21 | onClickRefresh(evt: Event) { 22 | this.valChange.emit(evt) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /view/src/app/shared/navigation-bar/navigation-bar.component.scss: -------------------------------------------------------------------------------- 1 | mat-toolbar{ 2 | height: 58px; 3 | } -------------------------------------------------------------------------------- /view/src/app/shared/navigation-bar/navigation-bar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NavigationBarComponent } from './navigation-bar.component'; 4 | 5 | describe('NavigationBarComponent', () => { 6 | let component: NavigationBarComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NavigationBarComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NavigationBarComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/password/password.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/shared/password/password.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PasswordComponent } from './password.component'; 4 | 5 | describe('PasswordComponent', () => { 6 | let component: PasswordComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ PasswordComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PasswordComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/sign-in/sign-in.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .fill{ 5 | height: 36px; 6 | } 7 | .mat-spinner{ 8 | margin-left: 8px; 9 | } -------------------------------------------------------------------------------- /view/src/app/shared/sign-in/sign-in.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SignInComponent } from './sign-in.component'; 4 | 5 | describe('SignInComponent', () => { 6 | let component: SignInComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SignInComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SignInComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/tree-select/tree-select.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Error

5 |
6 | {{err}} 7 |
8 |
9 | 10 |

Select Group

11 |
12 | 13 |
14 |
15 | 16 | 17 |
18 |
-------------------------------------------------------------------------------- /view/src/app/shared/tree-select/tree-select.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } -------------------------------------------------------------------------------- /view/src/app/shared/tree-select/tree-select.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TreeSelectComponent } from './tree-select.component'; 4 | 5 | describe('TreeSelectComponent', () => { 6 | let component: TreeSelectComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ TreeSelectComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(TreeSelectComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/tree/tree.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/shared/tree/tree.component.scss -------------------------------------------------------------------------------- /view/src/app/shared/tree/tree.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TreeComponent } from './tree.component'; 4 | 5 | describe('TreeComponent', () => { 6 | let component: TreeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ TreeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(TreeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/upgraded/upgraded.component.html: -------------------------------------------------------------------------------- 1 |

Upgraded

2 | 3 |
4 | new version "{{upgraded}}" is ready, wait until the server restarts to take effect. 5 |
-------------------------------------------------------------------------------- /view/src/app/shared/upgraded/upgraded.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/app/shared/upgraded/upgraded.component.scss -------------------------------------------------------------------------------- /view/src/app/shared/upgraded/upgraded.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UpgradedComponent } from './upgraded.component'; 4 | 5 | describe('UpgradedComponent', () => { 6 | let component: UpgradedComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UpgradedComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UpgradedComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/shared/upgraded/upgraded.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject, OnInit } from '@angular/core'; 2 | import { MAT_DIALOG_DATA } from '@angular/material/dialog'; 3 | 4 | @Component({ 5 | selector: 'app-upgraded', 6 | templateUrl: './upgraded.component.html', 7 | styleUrls: ['./upgraded.component.scss'] 8 | }) 9 | export class UpgradedComponent implements OnInit { 10 | 11 | constructor(@Inject(MAT_DIALOG_DATA) public readonly upgraded: string) { } 12 | 13 | ngOnInit(): void { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /view/src/app/user/dialog/add/add.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } 7 | .mat-checkbox{ 8 | margin-right: 8px; 9 | } 10 | .fill{ 11 | padding-bottom: 24px; 12 | } -------------------------------------------------------------------------------- /view/src/app/user/dialog/add/add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AddComponent } from './add.component'; 4 | 5 | describe('AddComponent', () => { 6 | let component: AddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/dialog/delete/delete.component.html: -------------------------------------------------------------------------------- 1 |

delete {{data.name}}

2 | 3 |
4 | Once deleted, the data cannot be recovered. Please confirm the operation. 5 |
6 |
7 | 9 | 10 | 11 |
-------------------------------------------------------------------------------- /view/src/app/user/dialog/delete/delete.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/user/dialog/delete/delete.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DeleteComponent } from './delete.component'; 4 | 5 | describe('DeleteComponent', () => { 6 | let component: DeleteComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DeleteComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DeleteComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/dialog/edit/edit.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } 7 | .mat-checkbox{ 8 | margin-right: 8px; 9 | } 10 | .fill{ 11 | padding-bottom: 24px; 12 | } -------------------------------------------------------------------------------- /view/src/app/user/dialog/edit/edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditComponent } from './edit.component'; 4 | 5 | describe('EditComponent', () => { 6 | let component: EditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/dialog/group/group.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/user/dialog/group/group.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { GroupComponent } from './group.component'; 4 | 5 | describe('GroupComponent', () => { 6 | let component: GroupComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ GroupComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(GroupComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/dialog/password/password.component.scss: -------------------------------------------------------------------------------- 1 | .dialog-content{ 2 | max-width: 600px; 3 | } 4 | .mat-spinner{ 5 | margin-left: 8px; 6 | } -------------------------------------------------------------------------------- /view/src/app/user/dialog/password/password.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PasswordComponent } from './password.component'; 4 | 5 | describe('PasswordComponent', () => { 6 | let component: PasswordComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ PasswordComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PasswordComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/query/query.component.scss: -------------------------------------------------------------------------------- 1 | .query{ 2 | padding-right: 16px; 3 | } 4 | table { 5 | width: 100%; 6 | } -------------------------------------------------------------------------------- /view/src/app/user/query/query.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { QueryComponent } from './query.component'; 4 | 5 | describe('QueryComponent', () => { 6 | let component: QueryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ QueryComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(QueryComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /view/src/app/user/user-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { QueryComponent } from './query/query.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: QueryComponent, 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class UserRoutingModule { } 17 | -------------------------------------------------------------------------------- /view/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/.gitkeep -------------------------------------------------------------------------------- /view/src/assets/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-128x128.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-144x144.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-152x152.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-192x192.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-384x384.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-512x512.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-72x72.png -------------------------------------------------------------------------------- /view/src/assets/icons/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/powerpuffpenguin/webpc/c80f7b32615aa60e0bb97178355ef7859dc89ad4/view/src/assets/icons/icon-96x96.png -------------------------------------------------------------------------------- /view/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | aesKey: '8ed976ff-3ad3-4564-9e58-2abf169428db', 4 | aesIV: 'cf7bccc6-c562-466c-9ccb-a405527211d4', 5 | }; 6 | -------------------------------------------------------------------------------- /view/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | aesKey: 'aes key', 8 | aesIV: 'aes iv', 9 | }; 10 | 11 | /* 12 | * For easier debugging in development mode, you can import the following file 13 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 14 | * 15 | * This import should be commented out in production mode because it will have a negative impact 16 | * on performance if an error is thrown. 17 | */ 18 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 19 | -------------------------------------------------------------------------------- /view/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebPC 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /view/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /view/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import "xterm/css/xterm.css"; 3 | @import 'ngx-toastr/toastr'; 4 | 5 | .terminal { 6 | padding-left: 4px; 7 | } 8 | 9 | .fill-flex { 10 | flex: 1 1 auto; 11 | } 12 | 13 | .hide { 14 | display: none; 15 | } 16 | 17 | .iconfont { 18 | font-size: 24px; 19 | } 20 | 21 | .fullwidth { 22 | width: 100%; 23 | } 24 | 25 | .viewcard { 26 | padding: 18px 8px 8px; 27 | } 28 | 29 | .view { 30 | padding: 18px 8px 8px; 31 | } 32 | 33 | @media screen and (max-width: 851px) { 34 | .dialog-content { 35 | min-width: calc(100vw - 250px); 36 | } 37 | } 38 | 39 | @media screen and (min-width: 850px) { 40 | .dialog-content { 41 | min-width: 600px; 42 | } 43 | } 44 | 45 | .left8 { 46 | margin-left: 8px; 47 | } -------------------------------------------------------------------------------- /view/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /view/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /view/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "declaration": false, 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "es2020", 18 | "module": "es2020", 19 | "lib": [ 20 | "ES2022", 21 | "dom" 22 | ] 23 | }, 24 | "angularCompilerOptions": { 25 | "strictInjectionParameters": true, 26 | "strictTemplates": true 27 | } 28 | } -------------------------------------------------------------------------------- /view/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /view/tsconfig.worker.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/worker", 6 | "lib": [ 7 | "es2018", 8 | "webworker" 9 | ], 10 | "types": [] 11 | }, 12 | "include": [ 13 | "src/**/*.worker.ts" 14 | ] 15 | } 16 | --------------------------------------------------------------------------------