Browse Source

Node-16 docker build

pull/396/head
Gyarbij 4 years ago
parent
commit
993d84ba71
No known key found for this signature in database GPG Key ID: 475E97703A86E06
  1. 70
      .github/workflows/codeql-analysis.yml
  2. 7
      Dockerfile
  3. 11
      LICENSE.md
  4. 17
      README.md
  5. 5
      docker-compose.dev.yml
  6. 6
      docker-compose.yml
  7. 13
      docs/changelog.json
  8. 2
      package-lock.json
  9. 2
      package.json
  10. 2
      src/config.js
  11. 10
      src/lib/Server.js
  12. 6
      src/lib/WireGuard.js
  13. 1936
      src/package-lock.json
  14. 22
      src/package.json
  15. 83
      src/www/index.html
  16. 2
      src/www/js/api.js
  17. 92
      src/www/js/app.js
  18. 14
      src/www/js/vendor/apexcharts.min.js
  19. 7
      src/www/js/vendor/vue-apexcharts.min.js

70
.github/workflows/codeql-analysis.yml

@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '20 21 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

7
Dockerfile

@ -1,4 +1,5 @@
FROM docker.io/library/node:17-alpine@sha256:0e83c810225bc29e614189acf3d6419e3c09881cefb9f7a170fdcfe3e15bbfd5 AS build_node_modules
# There's an issue with node:16-alpine on pi
FROM node:16.15.1-alpine AS build_node_modules
# Copy Web UI
COPY src/ /app/
@ -7,7 +8,7 @@ RUN npm ci --production
# Copy build result to a new image.
# This saves a lot of disk space.
FROM docker.io/library/node:17-alpine@sha256:0e83c810225bc29e614189acf3d6419e3c09881cefb9f7a170fdcfe3e15bbfd5
FROM node:16.15.1-alpine
COPY --from=build_node_modules /app /app
# Move node_modules one directory up, so during development
@ -36,4 +37,4 @@ ENV DEBUG=Server,WireGuard
# Run Web UI
WORKDIR /app
CMD ["/usr/bin/dumb-init", "node", "server.js"]
CMD ["/usr/bin/dumb-init", "node", "server.js"]

11
LICENSE.md

@ -0,0 +1,11 @@
**You may:**
* Use this software for yourself;
* Use this software for a company;
* Modify this software, as long as you:
* Publish the changes on GitHub as an open-source & linked fork;
* Don't remove any links to the original project or donation pages;
**You may not:**
* Use this software in a commercial product without a license from the original author;

17
README.md

@ -1,10 +1,5 @@
# WireUI
[![Build & Publish Docker Image to Docker Hub](https://github.com/WeeJeWel/wg-easy/actions/workflows/deploy.yml/badge.svg?branch=production)](https://github.com/WeeJeWel/wg-easy/actions/workflows/deploy.yml)
[![Lint](https://github.com/WeeJeWel/wg-easy/actions/workflows/lint.yml/badge.svg?branch=master)](https://github.com/WeeJeWel/wg-easy/actions/workflows/lint.yml)
[![Docker](https://img.shields.io/docker/v/weejewel/wg-easy/latest)](https://hub.docker.com/r/weejewel/wg-easy)
[![Docker](https://img.shields.io/docker/pulls/gyarbij/wireui.svg)](https://hub.docker.com/r/gyarbij/wireui)
This is a security and hardenig divergent fork of [wg-easy](https://github.com/WeeJeWel/wg-easy)
<p align="center">
@ -41,16 +36,16 @@ $ exit
And log in again.
### 2. Run WireGuard Easy
### 2. Run WireUI
To automatically install & run wg-easy, simply run:
<pre>
$ docker run -d \
--name=wg-easy \
--name=wireui \
-e WG_HOST=<b>🚨YOUR_SERVER_IP</b> \
-e PASSWORD=<b>🚨YOUR_ADMIN_PASSWORD</b> \
-v ~/.wg-easy:/etc/wireguard \
-v ~/.wireui:/etc/wireguard \
-p 51820:51820/udp \
-p 51821:51821/tcp \
--cap-add=NET_ADMIN \
@ -94,9 +89,9 @@ These options can be configured by setting environment variables using `-e KEY="
To update to the latest version, simply run:
```bash
docker stop wg-easy
docker rm wg-easy
docker pull weejewel/wg-easy
docker stop wireui
docker rm wireui
docker pull gyarbij/wireui
```
And then run the `docker run -d \ ...` command above again.

5
docker-compose.dev.yml

@ -5,5 +5,6 @@ services:
command: npm run serve
volumes:
- ./src/:/app/
# environment:
# - PASSWORD=p
environment:
# - PASSWORD=p
- WG_HOST=dev.wireui.com

6
docker-compose.yml

@ -4,7 +4,7 @@ services:
environment:
# ⚠️ Required:
# Change this to your host's public address
- WG_HOST=raspberrypi.local
- WG_HOST=https://wireui.com
# Optional:
# - PASSWORD=foobar123
@ -13,6 +13,10 @@ services:
# - WG_DEFAULT_DNS=1.1.1.1
# - WG_MTU=1420
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
# - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
image: gyarbij/wireui
container_name: wireui

13
docs/changelog.json

@ -1,8 +1,5 @@
{
"1": "Initial version. Enjoy!",
"2": "You can now rename a client, and update the address. Enjoy!",
"3": "Many improvements and small changes. Enjoy!",
"4": "Now with pretty charts for client's network speed. Enjoy!",
"5": "Many small improvements & feature requests. Enjoy!",
"6": "Security updates that break shit, help fix it"
}
# Changelog
## v0.0.1
- Initial build

2
package-lock.json

@ -1,4 +1,4 @@
{
"version": "1.0.0",
"version": "0.0.1",
"lockfileVersion": 1
}

2
package.json

@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "0.0.1",
"scripts": {
"build": "DOCKER_BUILDKIT=1 docker build --tag wireui .",
"serve": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up",

2
src/config.js

@ -16,6 +16,7 @@ module.exports.WG_DEFAULT_DNS = typeof process.env.WG_DEFAULT_DNS === 'string'
: '1.1.1.1';
module.exports.WG_ALLOWED_IPS = process.env.WG_ALLOWED_IPS || '0.0.0.0/0, ::/0';
module.exports.WG_PRE_UP = process.env.WG_PRE_UP || '';
module.exports.WG_POST_UP = process.env.WG_POST_UP || `
iptables -t nat -A POSTROUTING -s ${module.exports.WG_DEFAULT_ADDRESS.replace('x', '0')}/24 -o eth0 -j MASQUERADE;
iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT;
@ -23,4 +24,5 @@ iptables -A FORWARD -i wg0 -j ACCEPT;
iptables -A FORWARD -o wg0 -j ACCEPT;
`.split('\n').join(' ');
module.exports.WG_PRE_DOWN = process.env.WG_PRE_DOWN || '';
module.exports.WG_POST_DOWN = process.env.WG_POST_DOWN || '';

10
src/lib/Server.js

@ -62,7 +62,7 @@ module.exports = class Server {
req.session.authenticated = true;
req.session.save();
debug(`New Session: ${req.session.id})`);
debug(`New Session: ${req.session.id}`);
}))
// WireGuard
@ -99,8 +99,12 @@ module.exports = class Server {
const { clientId } = req.params;
const client = await WireGuard.getClient({ clientId });
const config = await WireGuard.getClientConfiguration({ clientId });
const configName = client.name.replace(/[^a-zA-Z0-9_=+.-]/g, '-').replace(/(-{2,}|-$)/g, '-').replace(/-$/, '').substring(0, 32);
res.header('Content-Disposition', `attachment; filename="${configName}.conf"`);
const configName = client.name
.replace(/[^a-zA-Z0-9_=+.-]/g, '-')
.replace(/(-{2,}|-$)/g, '-')
.replace(/-$/, '')
.substring(0, 32);
res.header('Content-Disposition', `attachment; filename="${configName || clientId}.conf"`);
res.header('Content-Type', 'text/plain');
res.send(config);
}))

6
src/lib/WireGuard.js

@ -19,7 +19,9 @@ const {
WG_DEFAULT_ADDRESS,
WG_PERSISTENT_KEEPALIVE,
WG_ALLOWED_IPS,
WG_PRE_UP,
WG_POST_UP,
WG_PRE_DOWN,
WG_POST_DOWN,
} = require('../config');
@ -94,7 +96,9 @@ module.exports = class WireGuard {
PrivateKey = ${config.server.privateKey}
Address = ${config.server.address}/24
ListenPort = 51820
PreUp = ${WG_PRE_UP}
PostUp = ${WG_POST_UP}
PreDown = ${WG_PRE_DOWN}
PostDown = ${WG_POST_DOWN}
`;
@ -261,6 +265,8 @@ Endpoint = ${WG_HOST}:${WG_PORT}`;
config.clients[clientId] = client;
await this.saveConfig();
return client;
}
async deleteClient({ clientId }) {

1936
src/package-lock.json

File diff suppressed because it is too large

22
src/package.json

@ -1,7 +1,7 @@
{
"release": 5,
"release": 7,
"name": "wireui",
"version": "1.0.0",
"version": "0.0.1",
"description": "",
"main": "server.js",
"scripts": {
@ -9,18 +9,18 @@
"serve-with-password": "PASSWORD=wg npm run serve",
"lint": "eslint ."
},
"author": "Chono Nanton",
"license": "MIT",
"author": "Gyarbij",
"license": "GNU Affero",
"dependencies": {
"debug": "^4.3.3",
"express": "^4.17.3",
"express-session": "^1.17.2",
"qrcode": "^1.5.0",
"debug": "^4.3.1",
"express": "^4.17.1",
"express-session": "^1.17.1",
"qrcode": "^1.4.4",
"uuid": "^8.3.2"
},
"devDependencies": {
"eslint": "^8.11.0",
"eslint-config-athom": "^3.0.1"
"eslint": "^7.27.0",
"eslint-config-athom": "^2.1.0"
},
"nodemonConfig": {
"ignore": [
@ -28,6 +28,6 @@
]
},
"engines": {
"node": "17"
"node": "16"
}
}

83
src/www/index.html

@ -2,7 +2,7 @@
<html>
<head>
<title>WireGuard WireUI</title>
<title>WireGuard</title>
<link href="./css/vendor/tailwind.min.css" rel="stylesheet">
<link rel="manifest" href="./manifest.json">
<link rel="icon" type="image/png" href="./img/favicon.png">
@ -11,11 +11,17 @@
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<style>
[v-cloak] {
display: none;
}
</style>
<body class="bg-gray-50">
<div id="app">
<div class="container mx-auto max-w-3xl">
<div v-cloak class="container mx-auto max-w-3xl">
<div v-if="authenticated === true">
<span v-if="requiresPassword"
@ -41,7 +47,7 @@
<p>{{latestRelease.changelog}}</p>
</div>
<a href="https://github.com/Gyarbij/wireui#updating" target="_blank"
<a href="https://github.com/Gyarbij.wireui#updating" target="_blank"
class="p-3 rounded-md bg-white float-right font-sm font-semibold text-red-800 flex-shrink-0 border-2 border-red-800 hover:border-white hover:text-white hover:bg-red-800 transition-all">
Update →
</a>
@ -72,14 +78,47 @@
class="relative overflow-hidden border-b border-gray-100 border-solid">
<!-- Chart -->
<div class="absolute z-0 bottom-0 left-0 right-0" style="top: 60%;">
<apexchart width="100%" height="100%" :options="client.chartOptions" :series="client.transferTxSeries">
</apexchart>
</div>
<div class="absolute z-0 top-0 left-0 right-0" style="bottom: 60%;">
<apexchart width="100%" height="100%" :options="client.chartOptions" :series="client.transferRxSeries"
style="transform: scaleY(-1);">
</apexchart>
<div class="absolute z-0 bottom-0 left-0 right-0" style="width: 100%; height: 20%;">
<!-- Bar -->
<div v-for="(_, index) in client.transferTxHistory" :style="{
display: 'inline-flex',
alignItems: 'flex-end',
width: '2%', // 1/100th of client.transferTxHistory.length
height: '100%',
padding: '0 3px',
boxSizing: 'border-box',
fontSize: 0,
}">
<!-- TX -->
<div :style="{
minHeight: '0px',
minWidth: '2px',
maxWidth: '4px',
width: '50%',
marginRight: '1px',
height: Math.round((client.transferTxHistory[index]/client.transferMax)*100) + '%',
background: client.hoverTx
? '#992922'
: '#F3F4F6',
transition: 'all 0.2s',
borderRadius: '2px 2px 0 0',
}"></div>
<!-- RX -->
<div :style="{
minHeight: '0px',
minWidth: '2px',
maxWidth: '4px',
width: '50%',
height: Math.round((client.transferRxHistory[index]/client.transferMax)*100) + '%',
background: client.hoverRx
? '#992922'
: '#F0F1F3',
transition: 'all 0.2s',
borderRadius: '2px 2px 0 0',
}"></div>
</div>
</div>
<div class="relative p-5 z-10 flex flex-row">
@ -101,7 +140,7 @@
<div class="flex-grow">
<!-- Name -->
<div class="text-gray-700 group" :title="'Created at ' + dateTime(new Date(client.createdAt))">
<div class="text-gray-700 group" :title="'Created on ' + dateTime(new Date(client.createdAt))">
<!-- Show -->
<input v-show="clientEditNameId === client.id" v-model="clientEditName"
@ -154,7 +193,10 @@
</span>
<!-- Transfer TX -->
<span v-if="client.transferTx":title="'Total Download: ' + bytes(client.transferTx)">
<span v-if="client.transferTx" :title="'Total Download: ' + bytes(client.transferTx)"
@mouseover="client.hoverTx = clientsPersist[client.id].hoverTx = true;"
@mouseleave="client.hoverTx = clientsPersist[client.id].hoverTx = false;"
style="cursor: default;">
·
<svg class="align-middle h-3 inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor">
@ -166,7 +208,10 @@
</span>
<!-- Transfer RX -->
<span v-if="client.transferRx" :title="'Total Upload: ' + bytes(client.transferRx)">
<span v-if="client.transferRx" :title="'Total Upload: ' + bytes(client.transferRx)"
@mouseover="client.hoverRx = clientsPersist[client.id].hoverRx = true;"
@mouseleave="client.hoverRx = clientsPersist[client.id].hoverRx = false;"
style="cursor: default;">
·
<svg class="align-middle h-3 inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor">
@ -179,7 +224,7 @@
<!-- Last seen -->
<span v-if="client.latestHandshakeAt"
:title="'Last seen at ' + dateTime(new Date(client.latestHandshakeAt))">
:title="'Last seen on ' + dateTime(new Date(client.latestHandshakeAt))">
· {{new Date(client.latestHandshakeAt) | timeago}}
</span>
</div>
@ -465,16 +510,14 @@
</div>
<p class="text-center m-10 text-gray-300 text-xs">Made by <a target="_blank" class="hover:underline"
href="https://gyarbij.dev/wireui">Gyarbij</a> · <a class="hover:underline"
href="https://github.com/gyarbij/wireui" target="_blank">GitHub</a></p>
<p v-cloak class="text-center m-10 text-gray-300 text-xs">Made by <a target="_blank" class="hover:underline"
href="https://gyarbij.gg/?ref=wireui">Gyarbij</a> · <a class="hover:underline"
href="https://github.com/Gyarbij/wireui" target="_blank">GitHub</a></p>
</div>
<script src="./js/vendor/vue.min.js"></script>
<script src="./js/vendor/apexcharts.min.js"></script>
<script src="./js/vendor/vue-apexcharts.min.js"></script>
<script src="./js/vendor/md5.min.js"></script>
<script src="./js/vendor/timeago.min.js"></script>
<script src="./js/api.js"></script>

2
src/www/js/api.js

@ -6,7 +6,7 @@
class API {
async call({ method, path, body }) {
const res = await fetch(`/api${path}`, {
const res = await fetch(`./api${path}`, {
method,
headers: {
'Content-Type': 'application/json',

92
src/www/js/app.js

@ -25,9 +25,6 @@ function bytes(bytes, decimals, kib, maxunit) {
new Vue({
el: '#app',
components: {
apexchart: VueApexCharts,
},
data: {
authenticated: null,
authenticating: false,
@ -51,31 +48,36 @@ new Vue({
chartOptions: {
chart: {
background: 'transparent',
type: 'area',
type: 'bar',
stacked: false,
toolbar: {
show: false,
},
animations: {
enabled: false,
},
},
fill: {
type: 'gradient',
},
colors: ['#CCCCCC'],
colors: [
'#DDDDDD', // rx
'#EEEEEE', // tx
],
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
width: 0,
plotOptions: {
bar: {
horizontal: false,
},
},
xaxis: {
labels: {
show: false,
},
axisTicks: {
show: false,
show: true,
},
axisBorder: {
show: false,
show: true,
},
},
yaxis: {
@ -119,7 +121,9 @@ new Vue({
minute: 'numeric',
}).format(value);
},
async refresh() {
async refresh({
updateCharts = false,
} = {}) {
if (!this.authenticated) return;
const clients = await this.api.getClients();
@ -130,46 +134,38 @@ new Vue({
if (!this.clientsPersist[client.id]) {
this.clientsPersist[client.id] = {};
this.clientsPersist[client.id].transferRxHistory = Array(20).fill(0);
this.clientsPersist[client.id].transferRxHistory = Array(50).fill(0);
this.clientsPersist[client.id].transferRxPrevious = client.transferRx;
this.clientsPersist[client.id].transferTxHistory = Array(20).fill(0);
this.clientsPersist[client.id].transferTxHistory = Array(50).fill(0);
this.clientsPersist[client.id].transferTxPrevious = client.transferTx;
this.clientsPersist[client.id].chartOptions = {
...this.chartOptions,
yaxis: {
...this.chartOptions.yaxis,
max: () => this.clientsPersist[client.id].chartMax,
},
};
}
this.clientsPersist[client.id].transferRxCurrent = client.transferRx - this.clientsPersist[client.id].transferRxPrevious;
this.clientsPersist[client.id].transferRxPrevious = client.transferRx;
this.clientsPersist[client.id].transferTxCurrent = client.transferTx - this.clientsPersist[client.id].transferTxPrevious;
this.clientsPersist[client.id].transferTxPrevious = client.transferTx;
// Debug
// client.transferRx = this.clientsPersist[client.id].transferRxPrevious + Math.random() * 1000;
// client.transferTx = this.clientsPersist[client.id].transferTxPrevious + Math.random() * 1000;
if (updateCharts) {
this.clientsPersist[client.id].transferRxCurrent = client.transferRx - this.clientsPersist[client.id].transferRxPrevious;
this.clientsPersist[client.id].transferRxPrevious = client.transferRx;
this.clientsPersist[client.id].transferTxCurrent = client.transferTx - this.clientsPersist[client.id].transferTxPrevious;
this.clientsPersist[client.id].transferTxPrevious = client.transferTx;
this.clientsPersist[client.id].transferRxHistory.push(this.clientsPersist[client.id].transferRxCurrent);
this.clientsPersist[client.id].transferRxHistory.shift();
this.clientsPersist[client.id].transferRxHistory.push(this.clientsPersist[client.id].transferRxCurrent);
this.clientsPersist[client.id].transferRxHistory.shift();
this.clientsPersist[client.id].transferTxHistory.push(this.clientsPersist[client.id].transferTxCurrent);
this.clientsPersist[client.id].transferTxHistory.shift();
this.clientsPersist[client.id].transferTxHistory.push(this.clientsPersist[client.id].transferTxCurrent);
this.clientsPersist[client.id].transferTxHistory.shift();
}
client.transferTxCurrent = this.clientsPersist[client.id].transferTxCurrent;
client.transferTxSeries = [{
name: 'tx',
data: this.clientsPersist[client.id].transferTxHistory,
}];
client.transferRxCurrent = this.clientsPersist[client.id].transferRxCurrent;
client.transferRxSeries = [{
name: 'rx',
data: this.clientsPersist[client.id].transferRxHistory,
}];
this.clientsPersist[client.id].chartMax = Math.max(...this.clientsPersist[client.id].transferTxHistory, ...this.clientsPersist[client.id].transferRxHistory);
client.transferTxHistory = this.clientsPersist[client.id].transferTxHistory;
client.transferRxHistory = this.clientsPersist[client.id].transferRxHistory;
client.transferMax = Math.max(...client.transferTxHistory, ...client.transferRxHistory);
client.chartOptions = this.clientsPersist[client.id].chartOptions;
client.hoverTx = this.clientsPersist[client.id].hoverTx;
client.hoverRx = this.clientsPersist[client.id].hoverRx;
return client;
});
@ -256,7 +252,9 @@ new Vue({
.then(session => {
this.authenticated = session.authenticated;
this.requiresPassword = session.requiresPassword;
this.refresh().catch(err => {
this.refresh({
updateCharts: true,
}).catch(err => {
alert(err.message || err.toString());
});
})
@ -265,12 +263,14 @@ new Vue({
});
setInterval(() => {
this.refresh().catch(console.error);
this.refresh({
updateCharts: true,
}).catch(console.error);
}, 1000);
Promise.resolve().then(async () => {
const currentRelease = await this.api.getRelease();
const latestRelease = await fetch('https://weejewel.github.io/wg-easy/changelog.json')
const latestRelease = await fetch('https://gyarbij.github.io/wireui/changelog.json')
.then(res => res.json())
.then(releases => {
const releasesArray = Object.entries(releases).map(([version, changelog]) => ({

14
src/www/js/vendor/apexcharts.min.js

File diff suppressed because one or more lines are too long

7
src/www/js/vendor/vue-apexcharts.min.js

@ -1,7 +0,0 @@
/**
* Minified by jsDelivr using Terser v5.7.1.
* Original file: /npm/vue-apexcharts@1.6.2/dist/vue-apexcharts.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function (t, e) { "object" == typeof exports && "undefined" != typeof module ? module.exports = e(require("apexcharts/dist/apexcharts.min")) : "function" == typeof define && define.amd ? define(["apexcharts/dist/apexcharts.min"], e) : t.VueApexCharts = e(t.ApexCharts) }(this, (function (t) { "use strict"; function e(t) { return (e = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (t) { return typeof t } : function (t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t })(t) } function n(t, e, n) { return e in t ? Object.defineProperty(t, e, { value: n, enumerable: !0, configurable: !0, writable: !0 }) : t[e] = n, t } t = t && t.hasOwnProperty("default") ? t.default : t; var i = { props: { options: { type: Object }, type: { type: String }, series: { type: Array, required: !0, default: function () { return [] } }, width: { default: "100%" }, height: { default: "auto" } }, data: function () { return { chart: null } }, beforeMount: function () { window.ApexCharts = t }, mounted: function () { this.init() }, created: function () { var t = this; this.$watch("options", (function (e) { !t.chart && e ? t.init() : t.chart.updateOptions(t.options) })), this.$watch("series", (function (e) { !t.chart && e ? t.init() : t.chart.updateSeries(t.series) }));["type", "width", "height"].forEach((function (e) { t.$watch(e, (function () { t.refresh() })) })) }, beforeDestroy: function () { this.chart && this.destroy() }, render: function (t) { return t("div") }, methods: { init: function () { var e = this, n = { chart: { type: this.type || this.options.chart.type || "line", height: this.height, width: this.width, events: {} }, series: this.series }; Object.keys(this.$listeners).forEach((function (t) { n.chart.events[t] = e.$listeners[t] })); var i = this.extend(this.options, n); return this.chart = new t(this.$el, i), this.chart.render() }, isObject: function (t) { return t && "object" === e(t) && !Array.isArray(t) && null != t }, extend: function (t, e) { var i = this; "function" != typeof Object.assign && (Object.assign = function (t) { if (null == t) throw new TypeError("Cannot convert undefined or null to object"); for (var e = Object(t), n = 1; n < arguments.length; n++) { var i = arguments[n]; if (null != i) for (var r in i) i.hasOwnProperty(r) && (e[r] = i[r]) } return e }); var r = Object.assign({}, t); return this.isObject(t) && this.isObject(e) && Object.keys(e).forEach((function (o) { i.isObject(e[o]) && o in t ? r[o] = i.extend(t[o], e[o]) : Object.assign(r, n({}, o, e[o])) })), r }, refresh: function () { return this.destroy(), this.init() }, destroy: function () { this.chart.destroy() }, updateSeries: function (t, e) { return this.chart.updateSeries(t, e) }, updateOptions: function (t, e, n, i) { return this.chart.updateOptions(t, e, n, i) }, toggleSeries: function (t) { return this.chart.toggleSeries(t) }, showSeries: function (t) { this.chart.showSeries(t) }, hideSeries: function (t) { this.chart.hideSeries(t) }, appendSeries: function (t, e) { return this.chart.appendSeries(t, e) }, resetSeries: function () { this.chart.resetSeries() }, zoomX: function (t, e) { this.chart.zoomX(t, e) }, toggleDataPointSelection: function (t, e) { this.chart.toggleDataPointSelection(t, e) }, appendData: function (t) { return this.chart.appendData(t) }, addText: function (t) { this.chart.addText(t) }, addImage: function (t) { this.chart.addImage(t) }, addShape: function (t) { this.chart.addShape(t) }, dataURI: function () { return this.chart.dataURI() }, setLocale: function (t) { return this.chart.setLocale(t) }, addXaxisAnnotation: function (t, e) { this.chart.addXaxisAnnotation(t, e) }, addYaxisAnnotation: function (t, e) { this.chart.addYaxisAnnotation(t, e) }, addPointAnnotation: function (t, e) { this.chart.addPointAnnotation(t, e) }, removeAnnotation: function (t, e) { this.chart.removeAnnotation(t, e) }, clearAnnotations: function () { this.chart.clearAnnotations() } } }; return window.ApexCharts = t, i.install = function (e) { e.ApexCharts = t, window.ApexCharts = t, Object.defineProperty(e.prototype, "$apexcharts", { get: function () { return t } }) }, i }));
Loading…
Cancel
Save