├── .assets
├── 1.gif
├── 2.gif
└── df_powered_by.svg
├── .github
└── workflows
│ └── go.yml
├── .vscode
├── extensions.json
└── tasks.json
├── LICENSE
├── README.md
└── application
├── .dockerignore
├── Dockerfile
├── backend
├── .env example
├── .gitignore
├── app
│ ├── agent
│ │ ├── agent.go
│ │ └── agent_test.go
│ ├── containerdb
│ │ ├── containerdb.go
│ │ └── containerdb_test.go
│ ├── daemon
│ │ ├── daemon.go
│ │ └── daemon_test.go
│ ├── db
│ │ ├── db.go
│ │ └── db_test.go
│ ├── routes
│ │ ├── routes.go
│ │ └── routes_test.go
│ ├── statistics
│ │ ├── statistics.go
│ │ └── statistics_test.go
│ ├── streamer
│ │ ├── streamer.go
│ │ └── streamer_test.go
│ ├── userdb
│ │ ├── userdb.go
│ │ └── userdb_test.go
│ ├── util
│ │ ├── util.go
│ │ └── util_test.go
│ └── vars
│ │ └── vars.go
├── go.mod
├── go.sum
└── main.go
├── build.sh
├── frontend
├── .gitignore
├── .storybook
│ ├── main.cjs
│ ├── preview-head.html
│ └── preview.cjs
├── generate_font.js
├── index.html
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── favicon_package_v0.16.zip
│ ├── mstile-150x150.png
│ ├── safari-pinned-tab.svg
│ └── site.webmanifest
├── src
│ ├── App.svelte
│ ├── Stores
│ │ └── stores.js
│ ├── Theme.scss
│ ├── Views
│ │ ├── Login
│ │ │ ├── Login.scss
│ │ │ └── Login.svelte
│ │ ├── Logs
│ │ │ ├── Loader.svelte
│ │ │ ├── LogStringHeader.svelte
│ │ │ ├── LogsView.scss
│ │ │ ├── LogsViewHeder
│ │ │ │ └── LogsViewHeder.svelte
│ │ │ ├── NewLogsV2.svelte
│ │ │ ├── Spiner.svelte
│ │ │ └── functions.js
│ │ ├── Main
│ │ │ ├── Main.scss
│ │ │ ├── Main.svelte
│ │ │ └── SettingsController.svelte
│ │ └── ServiceSettings
│ │ │ ├── Acess.svelte
│ │ │ ├── General.svelte
│ │ │ ├── ServiceSettings.scss
│ │ │ ├── ServiceSettings.svelte
│ │ │ └── ServiceSettingsLeft.svelte
│ ├── assets
│ │ ├── logo
│ │ │ ├── logs.svg
│ │ │ └── logs2.svg
│ │ └── res
│ │ │ ├── font
│ │ │ ├── Alert.svg
│ │ │ ├── Archive.svg
│ │ │ ├── ArrowRight.svg
│ │ │ ├── Break.svg
│ │ │ ├── Burger.svg
│ │ │ ├── Chart.svg
│ │ │ ├── Clean.svg
│ │ │ ├── Clock.svg
│ │ │ ├── Close.svg
│ │ │ ├── Colums.svg
│ │ │ ├── Combine.svg
│ │ │ ├── Copy.svg
│ │ │ ├── Cut.svg
│ │ │ ├── Data.svg
│ │ │ ├── Down.svg
│ │ │ ├── EmptyHeart.svg
│ │ │ ├── Error.svg
│ │ │ ├── Eye.svg
│ │ │ ├── Filter.svg
│ │ │ ├── Group.svg
│ │ │ ├── Heart.svg
│ │ │ ├── Home.svg
│ │ │ ├── Info.svg
│ │ │ ├── Json.svg
│ │ │ ├── Last.svg
│ │ │ ├── Leters.svg
│ │ │ ├── Logout.svg
│ │ │ ├── Moon.svg
│ │ │ ├── Pencil.svg
│ │ │ ├── Plus.svg
│ │ │ ├── Pointer.svg
│ │ │ ├── Refresh.svg
│ │ │ ├── Search.svg
│ │ │ ├── Server.svg
│ │ │ ├── Share.svg
│ │ │ ├── ShareLink.svg
│ │ │ ├── Success.svg
│ │ │ ├── Sun.svg
│ │ │ ├── Tips.svg
│ │ │ ├── User.svg
│ │ │ ├── Warning.svg
│ │ │ ├── Wheel.svg
│ │ │ └── font-css.hbs
│ │ │ ├── onLogsFont.css
│ │ │ ├── onLogsFont.eot
│ │ │ ├── onLogsFont.html
│ │ │ ├── onLogsFont.svg
│ │ │ ├── onLogsFont.ttf
│ │ │ ├── onLogsFont.woff
│ │ │ └── onLogsFont.woff2
│ ├── lib
│ │ ├── Button
│ │ │ ├── Button.scss
│ │ │ ├── Button.stories.js
│ │ │ └── Button.svelte
│ │ ├── ButtonToBottom
│ │ │ ├── ButtonToBottom.scss
│ │ │ └── ButtonToBottom.svelte
│ │ ├── ChartMenu
│ │ │ ├── Chart.svelte
│ │ │ ├── ChartMenu.scss
│ │ │ └── MainChartMenu.svelte
│ │ ├── CheckBox
│ │ │ ├── CheckBox.scss
│ │ │ └── Checkbox.svelte
│ │ ├── ClientPanel
│ │ │ ├── ClientPanel.scss
│ │ │ └── ClientPanel.svelte
│ │ ├── CommonList
│ │ │ ├── CommonList.scss
│ │ │ └── CommonList.svelte
│ │ ├── ConfirmationMenu
│ │ │ ├── ConfirmationMenu.scss
│ │ │ └── ConfirmationMenu.svelte
│ │ ├── Container
│ │ │ ├── Container.scss
│ │ │ ├── Container.stories.js
│ │ │ ├── Container.svelte
│ │ │ └── ContainerView.svelte
│ │ ├── DropDown
│ │ │ ├── DropDown.scss
│ │ │ ├── DropDown.svelte
│ │ │ ├── DropDownAddHost.svelte
│ │ │ └── dropDownRow.svelte
│ │ ├── HostList
│ │ │ ├── HostList.scss
│ │ │ └── HostList.svelte
│ │ ├── Input
│ │ │ └── Input.svelte
│ │ ├── ListWithChoise
│ │ │ ├── ListWithChoise.scss
│ │ │ └── ListWithChoise.svelte
│ │ ├── LogsSize
│ │ │ ├── LogSize.scss
│ │ │ └── LogsSize.svelte
│ │ ├── LogsString
│ │ │ ├── LogsString.scss
│ │ │ ├── LogsString.stories.js
│ │ │ └── LogsString.svelte
│ │ ├── Modal
│ │ │ ├── Modal.scss
│ │ │ └── Modal.svelte
│ │ ├── NotFound
│ │ │ ├── Notfound.scss
│ │ │ └── Notfound.svelte
│ │ ├── OutsideClicker
│ │ │ └── OutsideClicker.js
│ │ ├── ProgressBar
│ │ │ ├── ProgressBar.scss
│ │ │ └── ProgressBar.svelte
│ │ ├── SecretModal
│ │ │ ├── DockerComposeSnippet.svelte
│ │ │ ├── DockerSnippet.svelte
│ │ │ ├── SecretModal.scss
│ │ │ └── SecretModal.svelte
│ │ ├── Stats
│ │ │ ├── Stats.scss
│ │ │ └── Stats.svelte
│ │ ├── StreamInfo
│ │ │ ├── StreamInfo.scss
│ │ │ └── StreamInfo.svelte
│ │ ├── Toast
│ │ │ ├── Toast.scss
│ │ │ └── Toast.svelte
│ │ └── UserMenu
│ │ │ ├── UserManageForm.svelte
│ │ │ ├── UserMenu.scss
│ │ │ └── UserMenu.svelte
│ ├── main.js
│ ├── main.scss
│ ├── utils
│ │ ├── _variables.scss
│ │ ├── changeKey.js
│ │ ├── fetch.js
│ │ └── functions.js
│ └── vite-env.d.ts
├── startDebug.js
├── storybook-static
│ ├── favicon.ico
│ ├── project.json
│ └── stories.json
└── vite.config.js
└── release.sh
/.assets/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/.assets/1.gif
--------------------------------------------------------------------------------
/.assets/2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/.assets/2.gif
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | jobs:
10 |
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 |
16 | - name: Set up Go
17 | uses: actions/setup-go@v3
18 | with:
19 | go-version: 1.19.1
20 |
21 | - name: Get coverage tool
22 | run: |
23 | cd application/backend
24 | go get golang.org/x/tools/cmd/cover
25 | REF=${{ github.ref }}
26 | IFS='/' read -ra PATHS <<< "$REF"
27 | BRANCH_NAME="${PATHS[1]}_${PATHS[2]}"
28 | echo $BRANCH_NAME
29 | echo "BRANCH=$(echo ${BRANCH_NAME})" >> $GITHUB_ENV
30 |
31 | - name: Create failing badge
32 | uses: schneegans/dynamic-badges-action@v1.0.0
33 | with:
34 | auth: ${{ secrets.GIST_SECRET }}
35 | gistID: 7a0933f8cba0bddbcc95c8b850e32663
36 | filename: onlogs_passing__${{ env.BRANCH }}.json
37 | label: Tests
38 | message: Failed
39 | color: red
40 | namedLogo: checkmarx
41 |
42 | - name: Test
43 | run: |
44 | cd application/backend
45 | go test ./... -coverprofile cover.out
46 | go tool cover -func cover.out > covered.txt
47 |
48 | - name: Get coverage
49 | run: |
50 | cd application/backend
51 | for word in $(cat covered.txt); do total_percent=$word; done
52 | echo $total_percent
53 | echo "COVERAGE=$total_percent" >> $GITHUB_ENV
54 |
55 | - name: Create passing badge
56 | uses: schneegans/dynamic-badges-action@v1.0.0
57 | if: ${{ env.COVERAGE!=null }}
58 | with:
59 | auth: ${{ secrets.GIST_SECRET }}
60 | gistID: 7a0933f8cba0bddbcc95c8b850e32663
61 | filename: onlogs_passing__${{ env.BRANCH }}.json
62 | label: Tests
63 | message: Passed
64 | color: green
65 | namedLogo: checkmarx
66 |
67 | - name: Create coverage badge
68 | uses: schneegans/dynamic-badges-action@v1.0.0
69 | if: ${{ env.COVERAGE!=null }}
70 | with:
71 | auth: ${{ secrets.GIST_SECRET }}
72 | gistID: 7a0933f8cba0bddbcc95c8b850e32663
73 | filename: onlogs_units_coverage__${{ env.BRANCH }}.json
74 | label: Test Coverage
75 | message: ${{ env.COVERAGE }}
76 | color: green
77 | namedLogo: go
78 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["svelte.svelte-vscode"],
3 | "files.autoSave": "onFocusChange"
4 | }
5 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "Run front",
6 | "type": "shell",
7 | "command": "cd application/frontend && npm run dev",
8 | "presentation": {
9 | "reveal": "always",
10 | "panel": "new",
11 | "group": "develop"
12 | },
13 | "runOptions": { "runOn": "folderOpen" }
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Devforth.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/application/.dockerignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | frontend/node_modules
11 | frontend/dist
12 | frontend/dist-ssr
13 | frontend/*.local
14 | frontend/*.prettierrc
15 | frontend/.gitignore
16 |
17 | # Editor directories and files
18 | .vscode/*
19 | !.vscode/extensions.json
20 | .idea
21 | .DS_Store
22 | *.suo
23 | *.ntvs*
24 | *.njsproj
25 | *.sln
26 | *.sw?
27 |
28 | backend/.gitignore
29 | backend/dist
30 | leveldb
31 | *_test.go
32 |
33 | .assets/
34 | README.md
35 |
--------------------------------------------------------------------------------
/application/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:16-alpine AS frontbuilder
2 |
3 | WORKDIR /code/
4 | ADD frontend/package-lock.json .
5 | ADD frontend/package.json .
6 | RUN npm install -g npm:16 && npm ci
7 |
8 | ADD frontend/. .
9 |
10 | RUN npm run build
11 |
12 | COPY . /code/
13 |
14 | FROM alpine
15 |
16 | COPY --from=frontbuilder /code/dist/ /backend/dist/
17 |
18 | FROM golang:alpine AS backendbuilder
19 |
20 | ADD backend/. /backend/
21 | WORKDIR /backend/
22 |
23 | RUN go mod download \
24 | && go build -o onlogs .
25 |
26 | FROM alpine
27 |
28 | COPY --from=frontbuilder /code/dist/ /dist/
29 | COPY --from=backendbuilder /backend/onlogs /backend/onlogs
30 | CMD ["/backend/onlogs"]
31 |
--------------------------------------------------------------------------------
/application/backend/.env example:
--------------------------------------------------------------------------------
1 | PASSWORD=fsadfsadfad
2 | ENV_NAME = local
3 | PORT=2874
4 | ONLOGS_PATH_PREFIX=''
5 |
6 | # HOST=onlogs.coposter.me
7 | # AGENT=true
--------------------------------------------------------------------------------
/application/backend/.gitignore:
--------------------------------------------------------------------------------
1 | leveldb
2 | .env
3 | dist
--------------------------------------------------------------------------------
/application/backend/app/agent/agent.go:
--------------------------------------------------------------------------------
1 | package agent
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "io"
7 | "net/http"
8 | "os"
9 |
10 | "github.com/devforth/OnLogs/app/util"
11 | "github.com/devforth/OnLogs/app/vars"
12 | )
13 |
14 | func SendInitRequest(containers []string) {
15 | postBody, _ := json.Marshal(map[string]interface{}{
16 | "Hostname": util.GetHost(),
17 | "Token": os.Getenv("ONLOGS_TOKEN"),
18 | "Services": containers,
19 | })
20 | responseBody := bytes.NewBuffer(postBody)
21 |
22 | resp, err := http.Post(os.Getenv("HOST")+"/api/v1/addHost", "application/json", responseBody)
23 | if err != nil {
24 | panic("ERROR: Can't send request to host: " + err.Error())
25 | }
26 |
27 | if resp.StatusCode != 200 {
28 | b, _ := io.ReadAll(resp.Body)
29 | panic("ERROR: Response status from host is " + resp.Status + "\nResponse body: " + string(b))
30 | }
31 | }
32 |
33 | func SendLogMessage(token string, container string, message_item []string) bool {
34 | postBody, _ := json.Marshal(map[string]interface{}{
35 | "Host": util.GetHost(),
36 | "Token": token,
37 | "LogLine": []string{message_item[0], message_item[1]},
38 | "Container": container,
39 | })
40 | resp, err := http.Post(os.Getenv("HOST")+"/api/v1/addLogLine", "application/json", bytes.NewBuffer(postBody))
41 | if err != nil || resp.StatusCode != 200 {
42 | vars.BrokenLogs_DBs[container].Put([]byte(message_item[0]), []byte(message_item[1]), nil)
43 | return false
44 | }
45 | return true
46 | }
47 |
48 | func TryResend() {
49 | token := os.Getenv("ONLOGS_TOKEN")
50 | containers, _ := os.ReadDir("leveldb/hosts/" + util.GetHost() + "/containers/")
51 | for _, container := range containers {
52 | tmpDB := vars.BrokenLogs_DBs[container.Name()]
53 | if tmpDB == nil {
54 | tmpDB = util.GetDB(util.GetHost(), container.Name(), "/brokenLogs")
55 | defer tmpDB.Close()
56 | }
57 |
58 | iter := tmpDB.NewIterator(nil, nil)
59 | defer iter.Release()
60 | iter.First()
61 | if iter.Value() == nil {
62 | continue
63 | }
64 |
65 | if !SendLogMessage(token, container.Name(), []string{string(iter.Key()), string(iter.Value())}) {
66 | return
67 | }
68 | tmpDB.Delete(iter.Key(), nil)
69 |
70 | for iter.Next() {
71 | if !SendLogMessage(token, container.Name(), []string{string(iter.Key()), string(iter.Value())}) {
72 | return
73 | }
74 | tmpDB.Delete(iter.Key(), nil)
75 | }
76 | }
77 | }
78 |
79 | func SendUpdate(containers []string) {
80 | postBody, _ := json.Marshal(map[string]interface{}{
81 | "Hostname": util.GetHost(),
82 | "Token": os.Getenv("ONLOGS_TOKEN"),
83 | "Services": containers,
84 | })
85 | responseBody := bytes.NewBuffer(postBody)
86 |
87 | http.Post(os.Getenv("HOST")+"/api/v1/addHost", "application/json", responseBody)
88 | AskForDelete()
89 | }
90 |
91 | func AskForDelete() {
92 | postBody, _ := json.Marshal(map[string]interface{}{
93 | "Hostname": util.GetHost(),
94 | "Token": os.Getenv("ONLOGS_TOKEN"),
95 | })
96 | responseBody := bytes.NewBuffer(postBody)
97 |
98 | resp, _ := http.Post(os.Getenv("HOST")+"/api/v1/askForDelete", "application/json", responseBody)
99 |
100 | body, _ := io.ReadAll(resp.Body)
101 | if string(body) != "" {
102 | var toDelete map[string][]string
103 | json.Unmarshal(body, &toDelete)
104 |
105 | for _, container := range toDelete["Services"] {
106 | util.DeleteDockerLogs(util.GetHost(), container)
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/application/backend/app/agent/agent_test.go:
--------------------------------------------------------------------------------
1 | package agent
2 |
3 | import "testing"
4 |
5 | func TestSendInitRequest(t *testing.T) {
6 | defer func() {
7 | r := recover().(string)
8 | if r != "ERROR: Can't send request to host: Post \"/api/v1/addHost\": unsupported protocol scheme \"\"" {
9 | t.Error("Not expected error: ", r)
10 | }
11 | }()
12 | SendInitRequest([]string{})
13 | }
14 |
--------------------------------------------------------------------------------
/application/backend/app/containerdb/containerdb_test.go:
--------------------------------------------------------------------------------
1 | package containerdb
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/devforth/OnLogs/app/vars"
7 | "github.com/syndtr/goleveldb/leveldb"
8 | )
9 |
10 | func TestPutLogMessage(t *testing.T) {
11 | cont := "testCont"
12 | host := "testHost"
13 | vars.Container_Stat_Counter[host+"/"+cont] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0}
14 | db, _ := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+cont+"/logs", nil)
15 | statusDB, _ := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+cont+"statuses", nil)
16 | vars.Statuses_DBs[host+"/"+cont] = statusDB
17 | defer statusDB.Close()
18 | defer db.Close()
19 |
20 | PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:56:09.230421754Z", "vokAU6OdSulJGynsz wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"})
21 | PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:57:09.230421754Z", "ERROR wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"})
22 | PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:58:09.230421754Z", "WARN vokAU6OdSulJGynsz\r\n"})
23 | PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:59:09.230421754Z", "DEBUG wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"})
24 | PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:59:59.230421754Z", "INFO fasdfasdfB&^*inuk\r\n"})
25 |
26 | keys := []string{
27 | vars.Year + "-02-10T12:56:09.230421754Z", vars.Year + "-02-10T12:57:09.230421754Z",
28 | vars.Year + "-02-10T12:58:09.230421754Z", vars.Year + "-02-10T12:59:09.230421754Z",
29 | vars.Year + "-02-10T12:59:59.230421754Z",
30 | }
31 | for _, key := range keys {
32 | has, _ := db.Has([]byte(key), nil)
33 | if !has {
34 | t.Error("Key is not in db: " + key)
35 | }
36 | }
37 |
38 | PutLogMessage(db, host, cont, []string{"123", "fasdf\r\n"})
39 | has, _ := db.Has([]byte("123"), nil)
40 | if has {
41 | t.Error("Bad key is in db!")
42 | }
43 |
44 | defer func() {
45 | r := recover().(string)
46 | if r != "Host is not mentioned!" {
47 | t.Error("Not expected error: ", r)
48 | }
49 | }()
50 | PutLogMessage(db, "", cont, []string{vars.Year + "-02-10T12:57:09.230421754Z", "fasdf\r\n"})
51 | }
52 |
53 | func TestGetLogs(t *testing.T) {
54 | db, _ := leveldb.OpenFile("leveldb/hosts/Test/containers/TestGetLogsCont/logs", nil)
55 | vars.Container_Stat_Counter["Test/TestGetLogsCont"] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0}
56 | statusDB, _ := leveldb.OpenFile("leveldb/hosts/Test/containers/TestGetLogsCont/statuses", nil)
57 | vars.Statuses_DBs["Test/TestGetLogsCont"] = statusDB
58 | defer statusDB.Close()
59 |
60 | PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:57:09.230421754Z", "fasdf\r\n"})
61 | PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:51:09.230421754Z", "fasdf\r\n"})
62 | PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:52:09.230421754Z", "fasdf\r\n"})
63 | PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:53:09.230421754Z", "fasdf\r\n"})
64 | PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:54:09.230421754Z", "fasdf\r\n"})
65 | db.Close()
66 |
67 | var logs [][]string
68 | logs = GetLogs(false, true, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:57:09.230421754Z", false, nil)["logs"].([][]string)
69 | if len(logs) != 5 {
70 | t.Error("5 logItems must be returned!")
71 | }
72 | if logs[0][0] != vars.Year+"-02-10T12:57:09.230421754Z" {
73 | t.Error("Invalid first logItem datetime: ", logs[0][0])
74 | }
75 | if logs[4][0] != vars.Year+"-02-10T12:51:09.230421754Z" {
76 | t.Error("Invalid last logItem datetime: ", logs[4][0])
77 | }
78 |
79 | logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:51:09.230421754Z", false, nil)["logs"].([][]string)
80 | if len(logs) != 4 {
81 | t.Error("4 logItems must be returned!")
82 | }
83 | if logs[0][0] != vars.Year+"-02-10T12:52:09.230421754Z" {
84 | t.Error("Invalid first logItem datetime: ", logs[0][0])
85 | }
86 | if logs[3][0] != vars.Year+"-02-10T12:57:09.230421754Z" {
87 | t.Error("Invalid last logItem datetime: ", logs[3][0])
88 | }
89 |
90 | logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:51:09.230421753Z", false, nil)["logs"].([][]string)
91 | if len(logs) != 5 {
92 | t.Error("4 logItems must be returned!")
93 | }
94 | if logs[0][0] != vars.Year+"-02-10T12:51:09.230421754Z" {
95 | t.Error("Invalid first logItem datetime: ", logs[0][0])
96 | }
97 | if logs[4][0] != vars.Year+"-02-10T12:57:09.230421754Z" {
98 | t.Error("Invalid last logItem datetime: ", logs[3][0])
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/application/backend/app/daemon/daemon_test.go:
--------------------------------------------------------------------------------
1 | package daemon
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 | )
7 |
8 | func Test_validateMessage(t *testing.T) {
9 | type args struct {
10 | message string
11 | }
12 | tests := []struct {
13 | name string
14 | args args
15 | want string
16 | want1 bool
17 | }{
18 | {"Bad message", args{message: string([]byte{10})}, "", false},
19 | }
20 | for _, tt := range tests {
21 | t.Run(tt.name, func(t *testing.T) {
22 | got, got1 := validateMessage(tt.args.message)
23 | if !reflect.DeepEqual(got, tt.want) {
24 | t.Errorf("validateMessage() got = %v, want %v", got, tt.want)
25 | }
26 | if got1 != tt.want1 {
27 | t.Errorf("validateMessage() got1 = %v, want %v", got1, tt.want1)
28 | }
29 | })
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/application/backend/app/db/db.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/devforth/OnLogs/app/util"
7 | "github.com/devforth/OnLogs/app/vars"
8 | "github.com/syndtr/goleveldb/leveldb"
9 | )
10 |
11 | func CreateOnLogsToken() string {
12 | token := util.GenerateJWTSecret()
13 | to_put := time.Now().UTC().Add(24 * time.Hour).String()
14 | err := vars.TokensDB.Put([]byte(token), []byte(to_put), nil)
15 | if err != nil {
16 | vars.TokensDB.Close()
17 | vars.TokensDB, vars.TokensDBErr = leveldb.OpenFile("leveldb/tokens", nil)
18 |
19 | err = vars.TokensDB.Put([]byte(token), []byte(to_put), nil)
20 | if err != nil {
21 | panic(err)
22 | }
23 | }
24 | return token
25 | }
26 |
27 | func IsTokenExists(token string) bool {
28 | iter := vars.TokensDB.NewIterator(nil, nil)
29 | defer iter.Release()
30 | iter.First()
31 | if string(iter.Key()) == token {
32 | vars.TokensDB.Put([]byte(token), []byte("was used"), nil)
33 | return true
34 | }
35 | for iter.Next() {
36 | if string(iter.Key()) == token {
37 | vars.TokensDB.Put([]byte(token), []byte("was used"), nil)
38 | return true
39 | }
40 | }
41 | return false
42 | }
43 |
44 | func DeleteUnusedTokens() {
45 | for {
46 | db := vars.TokensDB
47 | iter := db.NewIterator(nil, nil)
48 | for iter.Next() {
49 | wasUsed := string(iter.Value())
50 | if wasUsed == "was used" {
51 | continue
52 | }
53 |
54 | created, _ := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", string(wasUsed))
55 | if created.Before(time.Now()) {
56 | db.Delete(iter.Key(), nil)
57 | }
58 | }
59 | iter.Release()
60 | db.Close()
61 | time.Sleep(time.Hour * 1)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/application/backend/app/db/db_test.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestIsTokenExists(t *testing.T) {
8 | type args struct {
9 | token string
10 | }
11 | tests := []struct {
12 | name string
13 | args args
14 | want bool
15 | }{
16 | {"Bad token", args{token: "fasdfadsf"}, false},
17 | {"Valid token", args{token: CreateOnLogsToken()}, true},
18 | }
19 | for _, tt := range tests {
20 | t.Run(tt.name, func(t *testing.T) {
21 | if got := IsTokenExists(tt.args.token); got != tt.want {
22 | t.Errorf("IsTokenExists() = %v, want %v", got, tt.want)
23 | }
24 | })
25 | }
26 | }
27 |
28 | func TestCreateOnLogsToken(t *testing.T) {
29 | token := CreateOnLogsToken()
30 | if !IsTokenExists(token) {
31 | t.Error("Invalid token")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/application/backend/app/statistics/statistics_test.go:
--------------------------------------------------------------------------------
1 | package statistics
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | "strings"
7 | "testing"
8 | "time"
9 |
10 | "github.com/devforth/OnLogs/app/vars"
11 | "github.com/syndtr/goleveldb/leveldb"
12 | )
13 |
14 | func TestRunStatisticForContainer(t *testing.T) {
15 | go RunStatisticForContainer("Test", "TestContainer")
16 | time.Sleep(1 * time.Second)
17 | if vars.Container_Stat_Counter["Test/TestContainer"] == nil {
18 | t.Error("No counter variable for container was created!")
19 | }
20 | if vars.Stat_Containers_DBs["Test/TestContainer"] == nil {
21 | t.Error("DB for stats wasn't created!")
22 | }
23 | }
24 |
25 | func TestGetStatisticsByService(t *testing.T) {
26 | vars.Container_Stat_Counter["test/test"] = map[string]uint64{"error": 1, "debug": 2, "info": 3, "warn": 4, "meta": 0, "other": 5}
27 | os.RemoveAll("leveldb/hosts/test/containers/test/statistics")
28 | statDB, _ := leveldb.OpenFile("leveldb/hosts/test/containers/test/statistics", nil)
29 | to_put, _ := json.Marshal(vars.Container_Stat_Counter["test/test"])
30 | datetime := strings.Replace(strings.Split(time.Now().UTC().String(), ".")[0], " ", "T", 1) + "Z"
31 | statDB.Put([]byte(datetime), to_put, nil)
32 | statDB.Close()
33 |
34 | res := GetStatisticsByService("test", "test", 2)
35 | if res["debug"] != 4 || res["error"] != 2 ||
36 | res["info"] != 6 || res["other"] != 10 ||
37 | res["warn"] != 8 {
38 | t.Error("Wrong value!\n", res)
39 | }
40 | }
41 |
42 | func TestGetChartData(t *testing.T) {
43 | cur_db, _ := leveldb.OpenFile("leveldb/hosts/test/statistics", nil)
44 | vars.Container_Stat_Counter["test/test"] = map[string]uint64{"error": 2, "debug": 1, "info": 3, "warn": 5, "meta": 0, "other": 4}
45 | vars.Stat_Containers_DBs["test/test"] = cur_db
46 | to_put, _ := json.Marshal(vars.Container_Stat_Counter["test/test"])
47 | datetime := strings.Replace(strings.Split(time.Now().UTC().String(), ".")[0], " ", "T", 1) + "Z"
48 | cur_db.Put([]byte(datetime), to_put, nil)
49 |
50 | res := GetChartData("test", "test", "hour", 2)
51 | datetime = datetime[:len(datetime)-6] + "00Z"
52 | if res[datetime]["debug"] != 1 || res[datetime]["error"] != 2 ||
53 | res[datetime]["info"] != 3 || res[datetime]["other"] != 4 ||
54 | res[datetime]["warn"] != 5 || res["now"]["debug"] != 1 ||
55 | res["now"]["error"] != 2 || res["now"]["info"] != 3 ||
56 | res["now"]["other"] != 4 || res["now"]["warn"] != 5 {
57 | t.Error("Wrong value!\n", res[datetime])
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/application/backend/app/streamer/streamer.go:
--------------------------------------------------------------------------------
1 | package streamer
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strconv"
7 | "time"
8 |
9 | "github.com/devforth/OnLogs/app/agent"
10 | "github.com/devforth/OnLogs/app/daemon"
11 | "github.com/devforth/OnLogs/app/statistics"
12 | "github.com/devforth/OnLogs/app/util"
13 | "github.com/devforth/OnLogs/app/vars"
14 | )
15 |
16 | func createStreams(containers []string) {
17 | for _, container := range vars.DockerContainers {
18 | if !util.Contains(container, vars.Active_Daemon_Streams) {
19 | go statistics.RunStatisticForContainer(util.GetHost(), container)
20 | vars.Active_Daemon_Streams = append(vars.Active_Daemon_Streams, container)
21 | if os.Getenv("AGENT") != "" {
22 | go daemon.CreateDaemonToHostStream(container)
23 | } else {
24 | go daemon.CreateDaemonToDBStream(container)
25 | }
26 | }
27 | }
28 | }
29 |
30 | func StreamLogs() {
31 | if vars.FavsDBErr != nil || vars.StateDBErr != nil || vars.UsersDBErr != nil {
32 | fmt.Println("ERROR: unable to open leveldb", vars.FavsDBErr, vars.StateDBErr, vars.UsersDBErr)
33 | return
34 | }
35 |
36 | vars.DockerContainers = daemon.GetContainersList()
37 | if os.Getenv("AGENT") != "" {
38 | agent.SendInitRequest(vars.DockerContainers)
39 | }
40 | for {
41 | createStreams(vars.DockerContainers)
42 | time.Sleep(20 * time.Second)
43 | vars.Year = strconv.Itoa(time.Now().UTC().Year())
44 | vars.DockerContainers = daemon.GetContainersList()
45 | if os.Getenv("AGENT") != "" {
46 | agent.SendUpdate(vars.DockerContainers)
47 | agent.TryResend()
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/application/backend/app/streamer/streamer_test.go:
--------------------------------------------------------------------------------
1 | package streamer
2 |
3 | import "testing"
4 |
5 | func Test_createStreams(t *testing.T) {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/application/backend/app/userdb/userdb.go:
--------------------------------------------------------------------------------
1 | package userdb
2 |
3 | import (
4 | "encoding/json"
5 | "errors"
6 | "os"
7 | "strings"
8 |
9 | "github.com/devforth/OnLogs/app/vars"
10 | "github.com/syndtr/goleveldb/leveldb"
11 | )
12 |
13 | func IsUserExists(login string) bool {
14 | isExists, _ := vars.UsersDB.Has([]byte(login), nil)
15 | return isExists
16 | }
17 |
18 | func CreateUser(login string, password string) error {
19 | if IsUserExists(login) {
20 | return errors.New("User is already exists")
21 | }
22 |
23 | vars.UsersDB.Put([]byte(login), []byte(password), nil)
24 | return nil
25 | }
26 |
27 | func GetUsers() []string {
28 | users := []string{}
29 | iter := vars.UsersDB.NewIterator(nil, nil)
30 | for iter.Next() {
31 | if string(iter.Key()) == os.Getenv("ADMIN_USERNAME") {
32 | continue
33 | }
34 | users = append(users, string(iter.Key()))
35 | }
36 | defer iter.Release()
37 |
38 | return users
39 | }
40 |
41 | func EditUser(login string, password string) {
42 | vars.UsersDB.Put([]byte(login), []byte(password), nil)
43 | }
44 |
45 | func DeleteUser(login string, password string) error {
46 | isExists, _ := vars.UsersDB.Has([]byte(login), nil)
47 | if !isExists {
48 | return errors.New("No such user")
49 | }
50 |
51 | vars.UsersDB.Delete([]byte(login), nil)
52 | return nil
53 | }
54 |
55 | func CheckUserPassword(login string, gotPassword string) bool {
56 | password, err := vars.UsersDB.Get([]byte(login), nil)
57 | if err != nil || strings.Compare(string(password), gotPassword) != 0 {
58 | return false
59 | }
60 |
61 | return true
62 | }
63 |
64 | func GetUserSettings(username string) map[string]interface{} {
65 | settingsDB, _ := leveldb.OpenFile("leveldb/usersSettings", nil)
66 | defer settingsDB.Close()
67 | var to_return map[string]interface{}
68 | result, _ := settingsDB.Get([]byte(username), nil)
69 | json.Unmarshal(result, &to_return)
70 | return to_return
71 | }
72 |
73 | func UpdateUserSettings(username string, settings map[string]interface{}) {
74 | settingsDB, _ := leveldb.OpenFile("leveldb/usersSettings", nil)
75 | defer settingsDB.Close()
76 | to_put, _ := json.Marshal(settings)
77 | settingsDB.Put([]byte(username), to_put, nil)
78 | }
79 |
--------------------------------------------------------------------------------
/application/backend/app/userdb/userdb_test.go:
--------------------------------------------------------------------------------
1 | package userdb
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/devforth/OnLogs/app/vars"
7 | )
8 |
9 | func TestIsUserExists(t *testing.T) {
10 | if IsUserExists("random") {
11 | t.Error("User shouldn't exist")
12 | }
13 | }
14 |
15 | func TestCreateUser(t *testing.T) {
16 | CreateUser("amogus", "sus")
17 | if !IsUserExists("amogus") {
18 | t.Error("User is not exist")
19 | }
20 |
21 | err := CreateUser("amogus", "sus")
22 | if err == nil || err.Error() != "User is already exists" {
23 | t.Error("Error \"User is already exists\" expected, got ", err)
24 | }
25 | }
26 |
27 | func TestGetUsers(t *testing.T) {
28 | CreateUser("admin", "admin")
29 | CreateUser("admin1", "admin")
30 | CreateUser("admin2", "admin")
31 |
32 | users := GetUsers()
33 | if len(users) < 3 {
34 | t.Error("Need more users")
35 | }
36 | }
37 |
38 | func TestEditUser(t *testing.T) {
39 | CreateUser("testtest", "testtest")
40 | EditUser("testtest", "sus?")
41 |
42 | pass, _ := vars.UsersDB.Get([]byte("testtest"), nil)
43 | if string(pass) != "sus?" {
44 | t.Error("User wasn't edited")
45 | }
46 | }
47 |
48 | func TestDeleteUser(t *testing.T) {
49 | err := DeleteUser("aaaaaaaaa????????", "123")
50 | if err == nil {
51 | t.Error("Error is nil")
52 | }
53 |
54 | DeleteUser("admin1", "admin")
55 | if IsUserExists("admin1") {
56 | t.Error("User should be deleted")
57 | }
58 | }
59 |
60 | func TestCheckUserPassword(t *testing.T) {
61 | CreateUser("testpassword", "123456")
62 | if !CheckUserPassword("testpassword", "123456") {
63 | t.Error("Password should be correct")
64 | }
65 | if CheckUserPassword("testpassword", "1") {
66 | t.Error("Password shouldn't be correct")
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/application/backend/app/util/util_test.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "net/http"
5 | "os"
6 | "testing"
7 |
8 | "github.com/devforth/OnLogs/app/vars"
9 | )
10 |
11 | func TestContains(t *testing.T) {
12 | type args struct {
13 | a string
14 | list []string
15 | }
16 | tests := []struct {
17 | name string
18 | args args
19 | want bool
20 | }{
21 | {"Is contain 'a'", args{a: "a", list: []string{"a", "b", "c"}}, true},
22 | {"Is contain 'A'", args{a: "A", list: []string{"a", "b", "c"}}, false},
23 | }
24 | for _, tt := range tests {
25 | t.Run(tt.name, func(t *testing.T) {
26 | if got := Contains(tt.args.a, tt.args.list); got != tt.want {
27 | t.Errorf("Contains() = %v, want %v", got, tt.want)
28 | }
29 | })
30 | }
31 | }
32 |
33 | func TestCreateInitUser(t *testing.T) {
34 | CreateInitUser()
35 | isExist, err := vars.UsersDB.Has([]byte("admin"), nil)
36 | if err != nil {
37 | t.Error(err.Error())
38 | }
39 | if !isExist {
40 | t.Error("User was not created!")
41 | }
42 | }
43 |
44 | func TestCreateJWT(t *testing.T) {
45 | os.Setenv("JWT_SERCRET", "1231efdZF")
46 | token := CreateJWT("test_user")
47 |
48 | test_req, _ := http.NewRequest("GET", "", nil)
49 | test_req.AddCookie(
50 | &http.Cookie{
51 | Name: "onlogs-cookie",
52 | Value: token,
53 | },
54 | )
55 |
56 | username, err := GetUserFromJWT(*test_req)
57 | if err != nil {
58 | t.Error(err)
59 | }
60 | if username != "test_user" {
61 | t.Error("Username in JWT is wrong: ", username)
62 | }
63 | }
64 |
65 | func TestGetHost(t *testing.T) {
66 | host, _ := os.Hostname()
67 | if host[len(host)-1] < 32 || host[len(host)-1] > 126 {
68 | host = host[:len(host)-1]
69 | }
70 |
71 | if GetHost() != host {
72 | t.Error("Hosts is not matching!")
73 | }
74 | }
75 |
76 | func TestGetUserFromJWT(t *testing.T) {
77 | os.Setenv("JWT_SERCRET", "1231efdZF")
78 |
79 | test_req1, _ := http.NewRequest("GET", "", nil)
80 | test_req1.AddCookie(
81 | &http.Cookie{
82 | Name: "onlogs-cookie",
83 | Value: CreateJWT("test_user"),
84 | },
85 | )
86 | test_req2, _ := http.NewRequest("GET", "", nil)
87 | test_req2.AddCookie(
88 | &http.Cookie{
89 | Name: "onlogs-cookie",
90 | Value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE2NzU4NDU4MDAsInVzZXIiOiJ0ZXN0X3VzZXIifQ.eqlUc3XkL8u-icC-2nihIrh1IedWP-cC9ewa4OI7wBg",
91 | },
92 | )
93 |
94 | test_req3, _ := http.NewRequest("GET", "", nil)
95 |
96 | username, _ := GetUserFromJWT(*test_req1)
97 | if username != "test_user" {
98 | t.Error("Username in JWT is wrong: ", username)
99 | }
100 |
101 | _, err := GetUserFromJWT(*test_req2)
102 | if err.Error() != "Token is expired" {
103 | t.Error("Token should be expired")
104 | }
105 |
106 | _, err = GetUserFromJWT(*test_req3)
107 | if err.Error() != "401 - Unauthorized!" {
108 | t.Error("Req should be unauthorized")
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/application/backend/app/vars/vars.go:
--------------------------------------------------------------------------------
1 | package vars
2 |
3 | import (
4 | "strconv"
5 | "sync"
6 | "time"
7 |
8 | "github.com/gorilla/websocket"
9 | "github.com/syndtr/goleveldb/leveldb"
10 | )
11 |
12 | var (
13 | ActiveDBs = map[string]*leveldb.DB{}
14 | Stat_Containers_DBs = map[string]*leveldb.DB{}
15 | Stat_Hosts_DBs = map[string]*leveldb.DB{}
16 | Statuses_DBs = map[string]*leveldb.DB{}
17 | BrokenLogs_DBs = map[string]*leveldb.DB{}
18 | ContainersMeta_DBs = map[string]*leveldb.DB{}
19 |
20 | Active_Daemon_Streams = []string{}
21 |
22 | DockerContainers = []string{}
23 | AgentsActiveContainers = map[string][]string{}
24 |
25 | ToDelete = map[string][]string{}
26 | Connections = map[string][]websocket.Conn{}
27 |
28 | Counters_For_Hosts_Last_30_Min = map[string]map[string]uint64{}
29 | Container_Stat_Counter = map[string]map[string]uint64{}
30 |
31 | Mutex sync.Mutex
32 | DBMutex sync.RWMutex
33 |
34 | FavsDB, FavsDBErr = leveldb.OpenFile("leveldb/favourites", nil)
35 | StateDB, StateDBErr = leveldb.OpenFile("leveldb/state", nil)
36 | UsersDB, UsersDBErr = leveldb.OpenFile("leveldb/users", nil)
37 | TokensDB, TokensDBErr = leveldb.OpenFile("leveldb/tokens", nil)
38 |
39 | Year = strconv.Itoa(time.Now().UTC().Year())
40 | )
41 |
42 | const (
43 | StatisticsSaveInterval = 1 * time.Minute
44 | )
45 |
46 | type UserData struct {
47 | Login string `json:"login"`
48 | Password string `json:"password"`
49 | }
50 |
--------------------------------------------------------------------------------
/application/backend/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/devforth/OnLogs
2 |
3 | go 1.19
4 |
5 | require (
6 | github.com/golang-jwt/jwt v3.2.2+incompatible
7 | github.com/gorilla/websocket v1.5.0
8 | github.com/joho/godotenv v1.4.0
9 | github.com/syndtr/goleveldb v1.0.0
10 | )
11 |
12 | require (
13 | github.com/golang/snappy v0.0.1 // indirect
14 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
15 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
16 | golang.org/x/text v0.3.7 // indirect
17 | gopkg.in/yaml.v2 v2.2.2 // indirect
18 | )
19 |
--------------------------------------------------------------------------------
/application/backend/go.sum:
--------------------------------------------------------------------------------
1 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
2 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
3 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
5 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
6 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
7 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
8 | github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
9 | github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
10 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
11 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
12 | github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
13 | github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
14 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
15 | github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
16 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
17 | github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
18 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
19 | github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
20 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
21 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
22 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
23 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
24 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
25 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
26 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
27 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
28 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
29 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
30 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
31 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
32 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
33 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
34 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
35 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
36 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
37 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
38 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
39 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
40 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
41 |
--------------------------------------------------------------------------------
/application/backend/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "os"
7 |
8 | "github.com/devforth/OnLogs/app/db"
9 | "github.com/devforth/OnLogs/app/routes"
10 | "github.com/devforth/OnLogs/app/streamer"
11 | "github.com/devforth/OnLogs/app/util"
12 | "github.com/joho/godotenv"
13 | )
14 |
15 | func init_config() {
16 | if os.Getenv("PORT") == "" {
17 | os.Setenv("PORT", "2874")
18 | }
19 |
20 | if os.Getenv("JWT_SECRET") == "" {
21 | token, err := os.ReadFile("leveldb/JWT_secret")
22 | if err != nil {
23 | os.WriteFile("leveldb/JWT_secret", []byte(os.Getenv("JWT_SECRET")), 0700)
24 | token, _ = os.ReadFile("leveldb/JWT_secret")
25 | }
26 | os.Setenv("JWT_SECRET", string(token))
27 | }
28 |
29 | if os.Getenv("DOCKER_SOCKET_PATH") == "" {
30 | os.Setenv("DOCKER_SOCKET_PATH", "/var/run/docker.sock")
31 | }
32 |
33 | if os.Getenv("MAX_LOGS_SIZE") == "" {
34 | os.Setenv("MAX_LOGS_SIZE", "10GB")
35 | }
36 |
37 | fmt.Println("INFO: OnLogs configs done!")
38 | }
39 |
40 | func main() {
41 | godotenv.Load(".env")
42 | init_config()
43 | if os.Getenv("AGENT") != "" {
44 | streamer.StreamLogs()
45 | }
46 |
47 | go db.DeleteUnusedTokens()
48 | go streamer.StreamLogs()
49 | // go util.RunSpaceMonitoring()
50 | util.ReplacePrefixVariableForFrontend()
51 | util.CreateInitUser()
52 |
53 | pathPrefix := os.Getenv("ONLOGS_PATH_PREFIX")
54 | http.HandleFunc(pathPrefix+"/", routes.Frontend)
55 | http.HandleFunc(pathPrefix+"/api/v1/addHost", routes.AddHost)
56 | http.HandleFunc(pathPrefix+"/api/v1/addLogLine", routes.AddLogLine)
57 | http.HandleFunc(pathPrefix+"/api/v1/askForDelete", routes.AskForDelete)
58 | http.HandleFunc(pathPrefix+"/api/v1/changeFavorite", routes.ChangeFavourite)
59 | http.HandleFunc(pathPrefix+"/api/v1/checkCookie", routes.CheckCookie)
60 | http.HandleFunc(pathPrefix+"/api/v1/createUser", routes.CreateUser)
61 | http.HandleFunc(pathPrefix+"/api/v1/deleteContainer", routes.DeleteContainer)
62 | http.HandleFunc(pathPrefix+"/api/v1/deleteContainerLogs", routes.DeleteContainerLogs)
63 | http.HandleFunc(pathPrefix+"/api/v1/deleteDockerLogs", routes.DeleteDockerLogs)
64 | http.HandleFunc(pathPrefix+"/api/v1/deleteUser", routes.DeleteUser)
65 | http.HandleFunc(pathPrefix+"/api/v1/editHostname", routes.EditHostname)
66 | http.HandleFunc(pathPrefix+"/api/v1/editUser", routes.EditUser)
67 | http.HandleFunc(pathPrefix+"/api/v1/getChartData", routes.GetChartData)
68 | http.HandleFunc(pathPrefix+"/api/v1/getDockerSize", routes.GetDockerSize)
69 | http.HandleFunc(pathPrefix+"/api/v1/getHosts", routes.GetHosts)
70 | http.HandleFunc(pathPrefix+"/api/v1/getLogWithPrev", routes.GetLogWithPrev)
71 | http.HandleFunc(pathPrefix+"/api/v1/getLogs", routes.GetLogs)
72 | http.HandleFunc(pathPrefix+"/api/v1/getLogsStream", routes.GetLogsStream)
73 | http.HandleFunc(pathPrefix+"/api/v1/getPrevLogs", routes.GetPrevLogs)
74 | http.HandleFunc(pathPrefix+"/api/v1/getSecret", routes.GetSecret)
75 | http.HandleFunc(pathPrefix+"/api/v1/getSizeByAll", routes.GetSizeByAll)
76 | http.HandleFunc(pathPrefix+"/api/v1/getSizeByService", routes.GetSizeByService)
77 | http.HandleFunc(pathPrefix+"/api/v1/getStats", routes.GetStats)
78 | http.HandleFunc(pathPrefix+"/api/v1/getStorageData", routes.GetStorageData)
79 | http.HandleFunc(pathPrefix+"/api/v1/getUserSettings", routes.GetUserSettings)
80 | http.HandleFunc(pathPrefix+"/api/v1/getUsers", routes.GetUsers)
81 | http.HandleFunc(pathPrefix+"/api/v1/login", routes.Login)
82 | http.HandleFunc(pathPrefix+"/api/v1/logout", routes.Logout)
83 | http.HandleFunc(pathPrefix+"/api/v1/updateUserSettings", routes.UpdateUserSettings)
84 |
85 | fmt.Println("Listening on port:", string(os.Getenv("PORT"))+"...")
86 | fmt.Println("ONLOGS: ", http.ListenAndServe(":"+string(os.Getenv("PORT")), nil))
87 | }
88 |
--------------------------------------------------------------------------------
/application/build.sh:
--------------------------------------------------------------------------------
1 | # docker buildx create --use
2 | docker buildx build --load --platform=linux/amd64,linux/arm64 --tag "devforth/onlogs:latest" --tag "devforth/onlogs:1.1.4" .
3 |
--------------------------------------------------------------------------------
/application/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | *.prettierrc
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 | .env
27 |
28 |
--------------------------------------------------------------------------------
/application/frontend/.storybook/main.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "stories": [
3 | "../src/**/*.stories.mdx",
4 | "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)"
5 | ],
6 | "addons": [
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials",
9 | "@storybook/addon-interactions"
10 | ],
11 | "framework": "@storybook/svelte",
12 | "core": {
13 | "builder": "@storybook/builder-vite"
14 | },
15 | "features": {
16 | "storyStoreV7": true
17 | }
18 | }
--------------------------------------------------------------------------------
/application/frontend/.storybook/preview-head.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/application/frontend/.storybook/preview.cjs:
--------------------------------------------------------------------------------
1 | import "../src/main.scss";
2 |
3 | export const parameters = {
4 | actions: { argTypesRegex: "^on[A-Z].*" },
5 | controls: {
6 | matchers: {
7 | color: /(background|color)$/i,
8 | date: /Date$/,
9 | },
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/application/frontend/generate_font.js:
--------------------------------------------------------------------------------
1 | import webfontsGenerator from "@vusion/webfonts-generator";
2 | import fs from "fs";
3 |
4 | fs.readdir("src/assets/res/font", function (err, items) {
5 | if (err) {
6 | console.log("cant read res directory");
7 | }
8 | const files = items
9 | .filter((i) => i.toLowerCase().endsWith(".svg"))
10 | .map((i) => {
11 | return `src/assets/res/font/${i}`;
12 | });
13 |
14 | webfontsGenerator(
15 | {
16 | files: files,
17 | dest: "src/assets/res",
18 | fontName: "onLogsFont",
19 |
20 |
21 | // https://github.com/nfroidure/svgicons2svgfont options
22 | normalize: true,
23 | html: true,
24 | cssTemplate: "src/assets/res/font/font-css.hbs",
25 | templateOptions: {
26 | classPrefix: "log-",
27 | baseSelector: ".log",
28 | },
29 | types: ["svg", "ttf", "woff", "woff2", "eot"],
30 | },
31 | function (error) {
32 | if (error) {
33 | console.log("Fail!", error);
34 | } else {
35 | console.log("Done!");
36 | }
37 | }
38 | );
39 | });
40 |
--------------------------------------------------------------------------------
/application/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | OnLogs
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/application/frontend/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "Node",
4 | "target": "ESNext",
5 | "module": "ESNext",
6 | /**
7 | * svelte-preprocess cannot figure out whether you have
8 | * a value or a type, so tell TypeScript to enforce using
9 | * `import type` instead of `import` for Types.
10 | */
11 | "importsNotUsedAsValues": "error",
12 | "isolatedModules": true,
13 | "resolveJsonModule": true,
14 | /**
15 | * To have warnings / errors of the Svelte compiler at the
16 | * correct position, enable source maps by default.
17 | */
18 | "sourceMap": true,
19 | "esModuleInterop": true,
20 | "skipLibCheck": true,
21 | "forceConsistentCasingInFileNames": true,
22 | "baseUrl": ".",
23 | /**
24 | * Typecheck JS in `.svelte` and `.js` files by default.
25 | * Disable this if you'd like to use dynamic types.
26 | */
27 | "checkJs": true
28 | },
29 | /**
30 | * Use global.d.ts instead of compilerOptions.types
31 | * to avoid limiting type declarations.
32 | */
33 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte", "generate_font.js"]
34 | }
35 |
--------------------------------------------------------------------------------
/application/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build --base=/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION ",
9 | "test": "vite build --base=/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION && node startDebug.js ",
10 | "preview": "vite preview",
11 | "sb": "start-storybook -p 6006",
12 | "build-storybook": "build-storybook",
13 | "buildfont": "node generate_font.js"
14 | },
15 | "devDependencies": {
16 | "@babel/core": "^7.19.3",
17 | "@storybook/addon-actions": "^6.5.12",
18 | "@storybook/addon-essentials": "^6.5.12",
19 | "@storybook/addon-interactions": "^6.5.12",
20 | "@storybook/addon-links": "^6.5.12",
21 | "@storybook/builder-vite": "^0.2.3",
22 | "@storybook/svelte": "^6.5.12",
23 | "@storybook/testing-library": "^0.0.13",
24 | "@sveltejs/vite-plugin-svelte": "^1.0.2",
25 | "eslint-plugin-svelte3": "^4.0.0",
26 | "fs-extra": "^11.1.0",
27 | "sass": "^1.55.0",
28 | "svelte": "^3.49.0",
29 | "svelte-intersection-observer": "^0.10.0",
30 | "vite": "^3.1.0"
31 | },
32 | "dependencies": {
33 | "@vusion/webfonts-generator": "^0.8.0",
34 | "chart.js": "^4.2.0",
35 | "json-to-html": "^0.1.2",
36 | "svelte-chartjs": "^3.1.2",
37 | "svelte-loading-spinners": "^0.3.4",
38 | "svelte-routing": "^1.6.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/application/frontend/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/application/frontend/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/application/frontend/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/application/frontend/public/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #da532c
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/application/frontend/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/favicon-16x16.png
--------------------------------------------------------------------------------
/application/frontend/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/favicon-32x32.png
--------------------------------------------------------------------------------
/application/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/application/frontend/public/favicon_package_v0.16.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/favicon_package_v0.16.zip
--------------------------------------------------------------------------------
/application/frontend/public/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/public/mstile-150x150.png
--------------------------------------------------------------------------------
/application/frontend/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/application/frontend/src/App.svelte:
--------------------------------------------------------------------------------
1 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | {#if $toastIsVisible} {/if}
97 |
98 |
--------------------------------------------------------------------------------
/application/frontend/src/Stores/stores.js:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 |
3 | export const store = writable({
4 | UTCtime: true,
5 | breakLines: true,
6 | // used insensitive prop coz for now default value MUST be true
7 | caseInSensitive: true,
8 | transformJson: true,
9 | deleteFromDocker: false,
10 | });
11 |
12 | //chosen logs string
13 | export const chosenLogsString = writable("");
14 |
15 | //modals state
16 | export const userMenuOpen = writable(false);
17 | export const userDeleteOpen = writable(false);
18 | export const addUserModalOpen = writable(false);
19 | export const editUserOpen = writable(false);
20 |
21 | export const theme = writable("light");
22 |
23 | // hosts service
24 |
25 | export const lastChosenHost = writable("");
26 | export const lastChosenService = writable("");
27 |
28 | // toast state
29 |
30 | export const toast = writable({
31 | tittle: "",
32 | message: "",
33 | position: "",
34 | status: "",
35 | additionButton: {},
36 | });
37 | export const toastIsVisible = writable(false);
38 | export const toastTimeoutId = writable(null);
39 |
40 | // active menu option
41 | export const activeMenuOption = writable("home");
42 |
43 | //add host menu
44 | export const addHostMenuIsVisible = writable(false);
45 |
46 | //snippet modal
47 | export const snipetModalIsVisible = writable(false);
48 | export const currentSnippedOption = writable("Docker");
49 |
50 | //hosts list scroll is visible
51 | export const listScrollIsVisible = writable(false);
52 |
53 | //confirmation menu
54 | export const confirmationObj = writable({
55 | action: function () {},
56 | message:
57 | "You want to delete host service logs. This data will be lost. This action cannot be undone.",
58 |
59 | isVisible: false,
60 | });
61 |
62 | //serviceSettings
63 | export const lastChosenSetting = writable("General");
64 |
65 | //make highlightsLogs
66 |
67 | export const lastLogTimestamp = writable(0);
68 |
69 | //stats
70 | export const lastStatsPeriod = writable(2);
71 | export const lastStatisticPeriod = writable("Per hour");
72 |
73 | //spiner
74 |
75 | export const isPending = writable(false);
76 |
77 | //url hash
78 |
79 | export const urlHash = writable("");
80 |
81 | //cancel fetch (for bed connection)
82 |
83 | export const isFeatching = writable(false);
84 | export const isSearching = writable(false);
85 |
86 | //status for serching logs by status
87 |
88 | export const chosenStatus = writable("");
89 |
90 | //last logTime for logsStream
91 | export const lastLogTime = writable("");
92 |
93 | // webSocket isMuted
94 | export const WSisMuted = writable(false);
95 | export const manuallyUnmuted = writable(false);
96 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Login/Login.scss:
--------------------------------------------------------------------------------
1 | div.login.contentContainer {
2 | display: flex;
3 | align-items: center;
4 | justify-content: center;
5 | }
6 |
7 | div.loginForm {
8 | display: flex;
9 | flex-direction: column;
10 | align-items: center;
11 | gap: 20px;
12 | padding: 0 15px 0 15px;
13 |
14 | h1#title {
15 | color: $active-color;
16 | }
17 |
18 | input {
19 | font-family: "Ubuntu";
20 | font-style: normal;
21 | font-weight: 700;
22 | font-size: 14px;
23 | height: 30px;
24 | padding-left: 15px;
25 | background-color: #f8fafb;
26 | border: 1px solid #a3a3b9;
27 | border-radius: 10px;
28 | :focus {
29 | outline: none;
30 | }
31 | }
32 |
33 | input.wrong {
34 | border: 1px solid red;
35 | }
36 |
37 | div.bottom {
38 | display: flex;
39 | width: 100%;
40 | align-items: center;
41 | justify-content: space-between;
42 |
43 | p {
44 | font-family: "Ubuntu";
45 | font-style: normal;
46 | // font-weight: 700;
47 | font-weight: 400;
48 | font-size: 12px;
49 | visibility: hidden;
50 | color: red;
51 | }
52 |
53 | p.wrong {
54 | visibility: initial;
55 | }
56 |
57 | div.confirmButton {
58 | box-shadow: 1px 1px 15px rgba(5, 39, 70, 0.3);
59 | border-radius: 20px;
60 | }
61 | }
62 | form {
63 | display: flex;
64 | flex-direction: column;
65 | gap: 20px;
66 | }
67 | }
68 | .loginContainer {
69 | display: flex;
70 | min-height: 25vh;
71 | min-width: 20vw;
72 |
73 | position: absolute;
74 | left: 50%;
75 | top: 50%;
76 | transform: translate(-50%, -50%);
77 | justify-content: center;
78 | align-items: center;
79 | background-color: $block-bg-color;
80 | border-radius: $main-border-radius;
81 | padding: $normal-padding;
82 | }
83 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Login/Login.svelte:
--------------------------------------------------------------------------------
1 |
45 |
46 |
84 |
85 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Logs/Loader.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Logs/LogStringHeader.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.svelte:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
36 | {#if !isSearchVIsible}
37 |
42 |
49 | {#if dropDownIsVisible}
50 |
51 | {/if}
52 |
53 |
54 | {}}
60 | />
61 |
62 | {/if}
63 |
64 | {
70 | isSearchVIsible = !isSearchVIsible;
71 | }}
72 | />
73 |
74 |
86 |
87 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Logs/Spiner.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/Main/SettingsController.svelte:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/ServiceSettings/Acess.svelte:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/src/Views/ServiceSettings/Acess.svelte
--------------------------------------------------------------------------------
/application/frontend/src/Views/ServiceSettings/General.svelte:
--------------------------------------------------------------------------------
1 |
43 |
44 |
45 |
Change settings for current service:
46 |
HOST: {$lastChosenHost}
47 |
SERVICE: {$lastChosenService}
48 |
49 |
50 | Delete this service
51 | Once you delete a service, there is no going back. Please be certain.
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/ServiceSettings/ServiceSettings.scss:
--------------------------------------------------------------------------------
1 | .serviceSettings {
2 | margin: $container-padding;
3 | @include for-mobile {
4 | text-align: center;
5 | margin: 0;
6 | margin-top: 30px;
7 | }
8 | .title {
9 | margin-bottom: 24px;
10 | padding-bottom: 16px;
11 | border-bottom: 1px solid $lines-color;
12 | }
13 | .text {
14 | margin: 16px;
15 | }
16 | .actionThumb {
17 | display: flex;
18 | justify-content: space-between;
19 | align-items: center;
20 | margin-top: 26px;
21 | @include for-mobile {
22 | flex-direction: column;
23 | text-align: center;
24 | }
25 | }
26 | .actionTitle {
27 | display: flex;
28 | flex-direction: column;
29 | @include for-mobile {
30 | margin-bottom: 12px;
31 | }
32 | }
33 | span {
34 | font-weight: 700;
35 | margin-bottom: 12px;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/ServiceSettings/ServiceSettings.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | {#if $lastChosenSetting.trim() === "General"}
9 |
10 | {/if}
11 | {#if $lastChosenSetting.trim() === "Acess"}
12 |
13 | {/if}
14 |
15 |
--------------------------------------------------------------------------------
/application/frontend/src/Views/ServiceSettings/ServiceSettingsLeft.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Alert.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Archive.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/ArrowRight.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Break.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Burger.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Chart.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Clean.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Clock.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Colums.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Combine.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Data.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Down.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/EmptyHeart.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Eye.svg:
--------------------------------------------------------------------------------
1 |
2 | />
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Filter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Heart.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Home.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Json.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Last.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Leters.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Logout.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Moon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Pencil.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Pointer.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Refresh.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Server.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Share.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/ShareLink.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Success.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Sun.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Tips.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/User.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Warning.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/Wheel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/font/font-css.hbs:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "{{fontName}}";
3 | src: {{{src}}};
4 | font-weight: normal;
5 | font-style: normal;
6 | }
7 |
8 | {{baseSelector}} {
9 | }
10 |
11 | {{baseSelector}}:before {
12 | font-family: {{fontName}} !important;
13 | font-style: normal !important;
14 | font-weight: normal !important;
15 | font-variant: normal !important;
16 | text-transform: none !important;
17 | speak: none;
18 | -webkit-font-smoothing: antialiased;
19 | -moz-osx-font-smoothing: grayscale;
20 | }
21 |
22 | {{#each codepoints}}
23 | .{{../classPrefix}}{{@key}}:before {
24 | content: "\\{{this}}";
25 | }
26 | {{/each}}
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/onLogsFont.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "onLogsFont";
3 | src: url("onLogsFont.eot?b1b1fa2c569a9742068bfa91c7006c7a?#iefix") format("embedded-opentype"),
4 | url("onLogsFont.woff2?b1b1fa2c569a9742068bfa91c7006c7a") format("woff2"),
5 | url("onLogsFont.woff?b1b1fa2c569a9742068bfa91c7006c7a") format("woff"),
6 | url("onLogsFont.ttf?b1b1fa2c569a9742068bfa91c7006c7a") format("truetype"),
7 | url("onLogsFont.svg?b1b1fa2c569a9742068bfa91c7006c7a#onLogsFont") format("svg");
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | .log {
13 | }
14 |
15 | .log:before {
16 | font-family: onLogsFont !important;
17 | font-style: normal !important;
18 | font-weight: normal !important;
19 | font-variant: normal !important;
20 | text-transform: none !important;
21 | speak: none;
22 | -webkit-font-smoothing: antialiased;
23 | -moz-osx-font-smoothing: grayscale;
24 | }
25 |
26 | .log-Alert:before {
27 | content: "\f101";
28 | }
29 | .log-Archive:before {
30 | content: "\f102";
31 | }
32 | .log-ArrowRight:before {
33 | content: "\f103";
34 | }
35 | .log-Break:before {
36 | content: "\f104";
37 | }
38 | .log-Burger:before {
39 | content: "\f105";
40 | }
41 | .log-Chart:before {
42 | content: "\f106";
43 | }
44 | .log-Clean:before {
45 | content: "\f107";
46 | }
47 | .log-Clock:before {
48 | content: "\f108";
49 | }
50 | .log-Close:before {
51 | content: "\f109";
52 | }
53 | .log-Colums:before {
54 | content: "\f10a";
55 | }
56 | .log-Combine:before {
57 | content: "\f10b";
58 | }
59 | .log-Copy:before {
60 | content: "\f10c";
61 | }
62 | .log-Cut:before {
63 | content: "\f10d";
64 | }
65 | .log-Data:before {
66 | content: "\f10e";
67 | }
68 | .log-Down:before {
69 | content: "\f10f";
70 | }
71 | .log-EmptyHeart:before {
72 | content: "\f110";
73 | }
74 | .log-Error:before {
75 | content: "\f111";
76 | }
77 | .log-Eye:before {
78 | content: "\f112";
79 | }
80 | .log-Filter:before {
81 | content: "\f113";
82 | }
83 | .log-Group:before {
84 | content: "\f114";
85 | }
86 | .log-Heart:before {
87 | content: "\f115";
88 | }
89 | .log-Home:before {
90 | content: "\f116";
91 | }
92 | .log-Info:before {
93 | content: "\f117";
94 | }
95 | .log-Json:before {
96 | content: "\f118";
97 | }
98 | .log-Last:before {
99 | content: "\f119";
100 | }
101 | .log-Leters:before {
102 | content: "\f11a";
103 | }
104 | .log-Logout:before {
105 | content: "\f11b";
106 | }
107 | .log-Moon:before {
108 | content: "\f11c";
109 | }
110 | .log-Pencil:before {
111 | content: "\f11d";
112 | }
113 | .log-Plus:before {
114 | content: "\f11e";
115 | }
116 | .log-Pointer:before {
117 | content: "\f11f";
118 | }
119 | .log-Refresh:before {
120 | content: "\f120";
121 | }
122 | .log-Search:before {
123 | content: "\f121";
124 | }
125 | .log-Server:before {
126 | content: "\f122";
127 | }
128 | .log-Share:before {
129 | content: "\f123";
130 | }
131 | .log-ShareLink:before {
132 | content: "\f124";
133 | }
134 | .log-Success:before {
135 | content: "\f125";
136 | }
137 | .log-Sun:before {
138 | content: "\f126";
139 | }
140 | .log-Tips:before {
141 | content: "\f127";
142 | }
143 | .log-User:before {
144 | content: "\f128";
145 | }
146 | .log-Warning:before {
147 | content: "\f129";
148 | }
149 | .log-Wheel:before {
150 | content: "\f12a";
151 | }
152 |
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/onLogsFont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/src/assets/res/onLogsFont.eot
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/onLogsFont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/src/assets/res/onLogsFont.ttf
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/onLogsFont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/src/assets/res/onLogsFont.woff
--------------------------------------------------------------------------------
/application/frontend/src/assets/res/onLogsFont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/src/assets/res/onLogsFont.woff2
--------------------------------------------------------------------------------
/application/frontend/src/lib/Button/Button.scss:
--------------------------------------------------------------------------------
1 | .button {
2 | font-family: "Ubuntu", sans-serif;
3 | line-height: 1;
4 | height: 100%;
5 |
6 | background-color: $btn-primary-color;
7 | border-radius: $main-border-radius;
8 |
9 | font-size: $main-font-s;
10 | color: $text-dark-color;
11 | font-weight: 400;
12 | line-height: $line-height;
13 | padding-left: $normal-padding;
14 | padding-right: $normal-padding;
15 | display: flex;
16 | justify-content: center;
17 | align-items: center;
18 | cursor: pointer;
19 |
20 | &.highlighted {
21 | background-color: $active-color;
22 | color: $text-onactive-color;
23 | }
24 | &.border {
25 | box-shadow: $main-shadow;
26 | }
27 |
28 | .iconWidthText {
29 | padding-right: $normal-padding;
30 | }
31 | &:disabled {
32 | opacity: 0.6;
33 | transform: none;
34 | cursor: auto;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Button/Button.stories.js:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import Button from "./Button.svelte";
3 | import { action } from "@storybook/addon-actions";
4 | import "../../assets/res/onLogsFont.css";
5 |
6 | export const actionsData = {
7 | onCkickButton: action("onClickButton"),
8 | };
9 |
10 | export default {
11 | component: Button,
12 | title: "Button",
13 | excludeStories: /.*Data$/,
14 | //👇 The argTypes are included so that they are properly displayed in the Actions Panel
15 | argTypes: {
16 | onCkickButton: { action: "onClickButton" },
17 | },
18 | };
19 |
20 | const Template = ({ onCkickButton, ...args }) => ({
21 | Component: Button,
22 | props: args,
23 | on: {
24 | ...actionsData,
25 | },
26 | });
27 |
28 | export const Default = Template.bind({});
29 | Default.args = {
30 | title: "Text",
31 | border: true,
32 | highlighted: false,
33 | minWidth: 90,
34 | minHeight: 32,
35 | icon: "",
36 | state: "BUTTON_TEXT",
37 | iconHeight: 12,
38 |
39 | };
40 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Button/Button.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 | {
27 | CB();
28 | return e;
29 | }}
30 | style:min-width={`${minWidth}px`}
31 | style:min-height={`${minHeight}px`}
32 | class="button block {highlighted ? 'highlighted' : ''} {border
33 | ? 'border'
34 | : ''}"
35 | >
36 | {title}
42 |
43 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.scss:
--------------------------------------------------------------------------------
1 | .buttonToBottomContainer {
2 | width: 40px;
3 | height: 40px;
4 |
5 | color: white;
6 | border-radius: $main-border-radius;
7 | box-shadow: $main-shadow;
8 | @include center;
9 | position: absolute;
10 | bottom: 20px;
11 | right: 20px;
12 | background-color: $active-color;
13 | opacity: 0.4;
14 | &:hover {
15 | opacity: 1;
16 | cursor: pointer;
17 | }
18 | .icoContainer {
19 | @include center;
20 | font-size: 14px;
21 | z-index: 4;
22 | color: $text-onactive-color;
23 | }
24 | @include for-mobile {
25 | bottom: 110px;
26 | }
27 |
28 | .buttonToBottomNumber {
29 | position: absolute;
30 | background-color: $background-color-dark;
31 | border-radius: 6px;
32 | min-width: 50%;
33 |
34 | top: 0;
35 | right: 0;
36 |
37 | padding: 2px;
38 |
39 | transform: translate(0, -70%);
40 | }
41 | }
42 |
43 | .subContainerMiddle .subContainer {
44 | position: relative;
45 | }
46 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
22 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ChartMenu/ChartMenu.scss:
--------------------------------------------------------------------------------
1 | .chartHeader {
2 | ul {
3 | margin-top: 12px;
4 | // gap: 6px;
5 | }
6 |
7 | .item {
8 | flex: 1;
9 | font-size: $main-font-m;
10 | box-shadow: $main-shadow-dark;
11 |
12 | cursor: pointer;
13 | &.isActive {
14 | color: $active-color;
15 | }
16 | &:first-child {
17 | border-top-left-radius: $main-border-radius;
18 | border-bottom-left-radius: $main-border-radius;
19 | }
20 | &:last-child {
21 | border-top-right-radius: $main-border-radius;
22 | border-bottom-right-radius: $main-border-radius;
23 | }
24 | // border-radius: $main-border-radius;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ChartMenu/MainChartMenu.svelte:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
Logs statistic:
29 |
30 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/CheckBox/CheckBox.scss:
--------------------------------------------------------------------------------
1 | .checkboxContainer {
2 | width: 47px;
3 | height: 28px;
4 | background-color: $lines-color;
5 | border-radius: 30px;
6 | display: flex;
7 | align-items: center;
8 | padding: 5px;
9 | box-sizing: border-box;
10 | justify-content: start;
11 | cursor: pointer;
12 | position: relative;
13 | }
14 |
15 | .active {
16 | .checkboxRoll {
17 | background-color: $active-color;
18 | position: absolute;
19 | transform: translateX(85%);
20 | transition: all 100ms;
21 | }
22 | }
23 |
24 | .inactive {
25 | .checkboxRoll {
26 | transform: translateX(0);
27 | transition: all 200ms;
28 | }
29 |
30 | .checkboxRoll {
31 | background-color: $btn-common-color;
32 | }
33 | }
34 |
35 | .checkboxRoll {
36 | width: 20px;
37 | height: 20px;
38 | background-color: $active-color;
39 | border-radius: 100%;
40 | }
41 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/CheckBox/Checkbox.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 |
29 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ClientPanel/ClientPanel.scss:
--------------------------------------------------------------------------------
1 | div.clientPanel {
2 | height: 100%;
3 | display: flex;
4 | align-items: center;
5 | justify-content: center;
6 |
7 | i {
8 | font-size: 27px;
9 | line-height: 1;
10 | color: $text-dark-color;
11 | }
12 | ul {
13 | display: flex;
14 | align-items: center;
15 | justify-content: center;
16 | height: 100%;
17 | }
18 | li {
19 | width: 100%;
20 | height: 100%;
21 | padding: 0%;
22 | cursor: pointer;
23 | margin: 0;
24 | position: relative;
25 | display: flex;
26 | align-items: center;
27 | justify-content: center;
28 | &:hover {
29 | opacity: 0.8;
30 | }
31 | &.active i {
32 | color: $active-color;
33 | }
34 |
35 | .higlightedOverlay.active {
36 | position: absolute;
37 |
38 | background-color: rgba(0, 0, 0, 0.05);
39 | width: 100%;
40 | height: calc(100% + 32px);
41 | top: -16px;
42 | left: 0;
43 | z-index: -1;
44 |
45 | &.active {
46 | background: rgba(140, 168, 254, 0.1);
47 | border-bottom: 6px solid $active-color;
48 | box-sizing: border-box;
49 | z-index: 1;
50 | }
51 | }
52 | }
53 |
54 | .clientPanelOptionsList {
55 | width: 100%;
56 | display: flex;
57 | justify-content: space-between;
58 | }
59 |
60 | .burger {
61 | @include for-tablet {
62 | @include hide;
63 | }
64 | }
65 | .burger {
66 | @include for-desctop {
67 | @include hide;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ClientPanel/ClientPanel.svelte:
--------------------------------------------------------------------------------
1 |
47 |
48 |
49 |
50 | {
52 | if ($activeMenuOption === "burger") {
53 | activeMenuOption.set(location.pathname.split("/")[1] || "home");
54 | } else {
55 | activeMenuOption.set("burger");
56 | }
57 | }}
58 | class="{$activeMenuOption === 'burger' && 'active'} burger"
59 | >
60 |
61 |
64 |
65 |
72 |
81 |
82 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/CommonList/CommonList.scss:
--------------------------------------------------------------------------------
1 | .commonList {
2 | margin-top: 24px;
3 | margin-left: 16px;
4 | margin-right: 16px;
5 | li {
6 | margin: 0;
7 | position: relative;
8 | cursor: default;
9 | &.clickable {
10 | cursor: pointer;
11 | }
12 | }
13 | li:hover {
14 | opacity: 0.8;
15 | .log {
16 | font-size: $main-font-l;
17 | opacity: 1;
18 | cursor: pointer;
19 | }
20 | }
21 | .listElement {
22 | @include center;
23 | justify-content: space-between;
24 | }
25 | .name {
26 | font-size: $main-font-s;
27 | }
28 | .log {
29 | font-size: $main-font-l;
30 | opacity: 0;
31 | }
32 | .highlightedOverlay {
33 | position: absolute;
34 |
35 | background-color: rgba(0, 0, 0, 0.05);
36 | width: calc(100% + 40px);
37 | height: 100%;
38 | top: 0;
39 | z-index: -1;
40 | margin-left: -16px;
41 | // margin-right: -16px;
42 |
43 | &.active {
44 | background: rgba(251, 252, 255, 0.1);
45 | border-left: 9px solid $text-dark-color-dark;
46 | box-sizing: border-box;
47 | z-index: 1;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/CommonList/CommonList.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 | {#each listData as listEl, index}
13 | {
16 | isRowClickable && storeProp?.set && storeProp.set(listEl.name);
17 | initialActive = null;
18 | listEl.callBack();
19 | }}
20 | >
21 |
26 |
27 |
28 |
29 |
34 |
35 | {/each}
36 |
37 |
38 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.scss:
--------------------------------------------------------------------------------
1 | .deleteModalContainer {
2 | background-color: $block-bg-color;
3 | font-size: $main-font-m;
4 | position: absolute;
5 | left: 50%;
6 | top: 50%;
7 | transform: translate(-50%, -50%);
8 | padding: $normal-padding;
9 | border-radius: $main-border-radius;
10 | box-shadow: $main-shadow;
11 | min-width: 350px;
12 | z-index: 7;
13 |
14 | max-width: 450px;
15 | @include for-mobile {
16 | width: 80vw;
17 | }
18 | .confirmationName {
19 | margin: 20px 0 20px 0;
20 | }
21 |
22 | .buttonsBox {
23 | display: flex;
24 | justify-content: space-between;
25 | margin-top: 24px;
26 | }
27 | .boldText {
28 | font-weight: 800;
29 | }
30 |
31 | .deleteModalTitle {
32 | margin-top: 16px;
33 | margin-bottom: 16px;
34 | text-align: center;
35 | }
36 |
37 | .optionsBox {
38 | display: flex;
39 | flex-direction: column;
40 | margin-top: 24px;
41 | margin-bottom: 24px;
42 | align-items: center;
43 | }
44 |
45 | .optionBox {
46 | display: grid;
47 | grid-template-columns: 1fr 1fr;
48 | // margin-left: 62px;
49 | p,
50 | .checkboxContainerThumb {
51 | display: flex;
52 | align-items: center;
53 | justify-content: center;
54 | }
55 | }
56 | .buttonsBox {
57 | display: flex;
58 | justify-content: space-between;
59 | align-items: center;
60 | margin-top: 24px;
61 | }
62 |
63 | .confirmationText {
64 | .boldText {
65 | font-weight: 700;
66 | }
67 | }
68 |
69 | .log-Tips {
70 | line-height: 1;
71 | font-size: $main-font-m;
72 | position: absolute;
73 | right: 16px;
74 | top: 16px;
75 | color: $lines-color;
76 | }
77 | }
78 | .tipsContainer {
79 | position: relative;
80 | }
81 |
82 | .tipsText {
83 | position: absolute;
84 | line-height: 1.5;
85 | top: 0%;
86 | right: 0%;
87 | transform: translate(106%);
88 | max-width: 236px;
89 | background-color: $block-bg-color;
90 | z-index: 8;
91 | height: 238px !important;
92 | font-size: $main-font-s;
93 | border-radius: $main-border-radius;
94 | box-shadow: $main-shadow;
95 | @include for-mobile {
96 | transform: translate(0%, -108%);
97 | }
98 | @include for-tablet {
99 | transform: translate(0%, -108%);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.svelte:
--------------------------------------------------------------------------------
1 |
68 |
69 |
70 |
71 |
{
74 | tipsIsVisible = true;
75 | }}
76 | on:mouseleave={() => {
77 | tipsIsVisible = false;
78 | }}
79 | />
80 | {#if tipsIsVisible}
81 |
82 | Delete Docker logs - when the option is set to
83 | "OFF"
84 | logs will be deleted only from onLogs. Logs will be available in docker containers, but not for onLogs.
85 | When
86 | enabled , each deletion of logs will
87 | clear logs from both onLogs and the
88 | Docker container
89 | .
90 |
{/if}
91 |
92 |
93 |
Delete logs options
94 |
95 |
96 |
Delete Docker logs
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | {`Host: ${
105 | $lastChosenHost ? $lastChosenHost : "host"
106 | }`}
107 |
108 |
109 | {`Service: ${
110 | $lastChosenService ? $lastChosenService : "service"
111 | }, from: `}
112 |
113 | {$confirmationObj.message}
116 |
117 |
This data will be lost. This action cannot be undone.
118 |
119 |
120 |
121 | Please type: "{confirmationWord}" to confirm.
124 |
125 |
126 |
132 |
133 |
134 | {
139 | if (confirmationWord === inputValue) {
140 | deletelogs();
141 | } else {
142 | error = true;
143 | }
144 | }}
145 | /> {
148 | confirmationObj.update((pv) => {
149 | return { ...pv, isVisible: false };
150 | });
151 | }}
152 | />
153 |
154 |
155 |
156 |
157 | {
159 | key === "Escape" && closeMenu();
160 |
161 | }}
162 | />
163 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Container/Container.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | font-family: "Ubuntu", sans-serif;
3 |
4 | background-color: $btn-primary-color;
5 | border-radius: $large-border-radius;
6 | color: $text-dark-color;
7 | padding-left: $container-padding;
8 | padding-right: $container-padding;
9 | padding-top: $container-vertical-padding;
10 | padding-bottom: $container-vertical-padding;
11 | box-sizing: border-box;
12 | height: 100%;
13 | @include for-mobile {
14 | padding: 12px;
15 | border-radius: 0px;
16 | }
17 |
18 | &.highlighted {
19 | background-color: $active-color;
20 | color: $text-onactive-color;
21 | }
22 | &.border {
23 | box-shadow: $container-shadow;
24 | }
25 | &.paddingOff {
26 | padding: 0;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Container/Container.stories.js:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import ContainerView from "./ContainerView.svelte";
3 | import Container from "./Container.svelte";
4 | import "../../assets/res/onLogsFont.css";
5 |
6 |
7 |
8 | export default {
9 | component: ContainerView,
10 | title: "Container",
11 | excludeStories: /.*Data$/,
12 | //👇 The argTypes are included so that they are properly displayed in the Actions Panel
13 | argTypes: {
14 |
15 | },
16 | };
17 |
18 | const Template = ({ ...args }) => ({
19 | Component: ContainerView,
20 | props: args,
21 | });
22 |
23 | export const Default = Template.bind({});
24 | Default.args = {
25 |
26 |
27 | newHighlighted: false,
28 |
29 | };
30 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Container/Container.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Container/ContainerView.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Slot 1
9 | Slot 2
10 | Slot 3
11 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/DropDown/DropDown.scss:
--------------------------------------------------------------------------------
1 | .dropDownContainer {
2 | box-shadow: $main-shadow;
3 | border-radius: $main-border-radius;
4 | background-color: $block-bg-color;
5 | padding: 20px;
6 | color: $text-dark-color;
7 | position: absolute;
8 | z-index: 5;
9 | width: max-content;
10 | right: 50%;
11 | top: 110%;
12 | transform: translate(50%);
13 | @include for-mobile {
14 | position: fixed;
15 | top: 60px;
16 | left: 0;
17 | transform: translate(20%, 0);
18 | }
19 |
20 | td {
21 | padding-top: 12px;
22 | vertical-align: middle;
23 | }
24 | & {
25 | right: 100%;
26 | transform: translate(25%);
27 | .dropDownRawEl.text {
28 | margin-right: 5px;
29 | }
30 | }
31 |
32 | &.addHost#addHost {
33 | @include for-mobile {
34 | padding: 12px;
35 | position: fixed;
36 | left: 0;
37 | right: 0;
38 | width: auto;
39 | top: 0;
40 | z-index: 150;
41 | transform: none;
42 | }
43 | }
44 | }
45 |
46 | .emptyBox {
47 | height: 28px;
48 | width: 1px;
49 | opacity: 0;
50 | }
51 |
52 | .dropDownRawEl.ico {
53 | margin-right: 12px;
54 | }
55 |
56 | .dropDownRawEl.text {
57 | margin-right: 26px;
58 | font-size: $main-font-s;
59 | }
60 |
61 | .rowContainer {
62 | margin-bottom: 20px;
63 | }
64 |
65 | .isFirst {
66 | td {
67 | padding-top: 0;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/DropDown/DropDown.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
14 |
19 |
24 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/DropDown/DropDownAddHost.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 | {}}
19 | />
20 | {
26 | snipetModalIsVisible.set(true);
27 | addHostMenuIsVisible.set(false);
28 | }}
29 | />
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/DropDown/dropDownRow.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 | {
21 | if (titleCallBack) {
22 | titleCallBack();
23 | }
24 | }}
25 | >
26 |
27 |
28 |
29 |
34 |
35 |
36 | {rowTitle}
37 |
38 | {#if !disableCheckbox}
40 | {:else}
41 |
42 | {/if}
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/HostList/HostList.scss:
--------------------------------------------------------------------------------
1 | .hostListHeader {
2 | font-size: $main-font-s;
3 | line-height: 1.14;
4 | font-weight: bold;
5 |
6 | ul {
7 | font-weight: 400;
8 | }
9 | .listName {
10 | font-weight: bold;
11 | }
12 | .icon {
13 | display: flex;
14 | align-items: center;
15 | vertical-align: baseline;
16 | position: relative;
17 | margin-bottom: 22px;
18 | }
19 | .log {
20 | margin-bottom: 5px;
21 | margin-right: 10px;
22 | font-size: 16px;
23 | line-height: 0.1;
24 | }
25 | }
26 |
27 | li {
28 | cursor: pointer;
29 | color: white;
30 | padding: 10px 0 10px 0;
31 | margin-bottom: 5px;
32 | }
33 |
34 | .selected {
35 | background-color: rgba(251, 252, 255, 0.1);
36 | padding: 10px 0 10px 15px;
37 | border-left: 5px solid white;
38 | margin: 0 -20px 5px -20px;
39 |
40 | .log.log-Wheel {
41 | padding-right: 20px;
42 | font-size: 20px;
43 | line-height: 1;
44 | float: right;
45 | }
46 | }
47 |
48 | .hosts {
49 | overflow-x: hidden;
50 | overflow-y: scroll;
51 | padding-right: 16px;
52 | height: 36vh;
53 |
54 | }
55 |
56 | .hosts::-webkit-scrollbar {
57 | width: 10px;
58 | height: 10px;
59 | background-color: #00000000;
60 | }
61 |
62 | .hosts::-webkit-scrollbar-thumb {
63 | background-color: #ffffff4a;
64 | border-radius: 10px;
65 | }
--------------------------------------------------------------------------------
/application/frontend/src/lib/HostList/HostList.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
19 |
20 |
21 |
22 | {#if servicesData != null}
23 | {#each servicesData as service}
24 | {#if selectedName.localeCompare(service) == 0}
25 | {service}
26 |
27 | {:else}
28 | {
30 | selectItem(service);
31 | }}
32 | >
33 | {service}
34 |
35 | {/if}
36 | {/each}
37 | {/if}
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Input/Input.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ListWithChoise/ListWithChoise.scss:
--------------------------------------------------------------------------------
1 | .listWithChoise {
2 | padding: $container-padding;
3 | padding-top: 0;
4 | padding-bottom: 0;
5 |
6 | overflow-y: overlay;
7 | overflow-x: auto;
8 |
9 | &::-webkit-scrollbar {
10 | width: 10px;
11 | height: 10px;
12 | background-color: rgba(0, 0, 0, 0);
13 | }
14 |
15 | &.active::-webkit-scrollbar-thumb {
16 | background-color: #0000002a;
17 | border-radius: 10px;
18 | }
19 |
20 | &::-webkit-scrollbar-corner {
21 | display: none;
22 | }
23 |
24 | .listElementButton {
25 | text-align: center;
26 | }
27 | .listElement {
28 | cursor: default;
29 | }
30 | .hostHeader:hover {
31 | opacity: 0.8;
32 | .headerButton {
33 | opacity: 1;
34 | }
35 | }
36 |
37 | .headerButton {
38 | opacity: 0;
39 | }
40 |
41 | .hostHeader {
42 | @include center;
43 | justify-content: start;
44 | gap: 12px;
45 | }
46 | .log-Pencil {
47 | font-size: 18px;
48 | }
49 |
50 | .hostName {
51 | font-weight: bold;
52 | font-size: $main-font-s;
53 | cursor: pointer;
54 | }
55 |
56 | .hostRow {
57 | @include center;
58 | justify-content: space-between;
59 | margin-left: $normal-padding;
60 | margin-right: $normal-padding;
61 |
62 | p {
63 | overflow: hidden;
64 | text-overflow: ellipsis;
65 | white-space: nowrap;
66 | font-size: $main-font-s;
67 | z-index: 3;
68 | cursor: pointer;
69 | }
70 | .disabled {
71 | opacity: 0.2;
72 | }
73 | }
74 | .highlightedOverlay {
75 | position: absolute;
76 |
77 | background-color: rgba(0, 0, 0, 0.05);
78 | width: 100%;
79 | height: 39px;
80 | top: 0;
81 | z-index: -1;
82 | &.active {
83 | background: rgba(251, 252, 255, 0.1);
84 | border-left: 9px solid $text-dark-color-dark;
85 | box-sizing: border-box;
86 | z-index: 1;
87 | }
88 | }
89 | li {
90 | margin-bottom: 0;
91 | cursor: pointer;
92 | }
93 |
94 | .listElementButton {
95 | .log-Heart {
96 | opacity: 1;
97 | }
98 | .log-EmptyHeart {
99 | opacity: 0;
100 | }
101 | .log-Wheel {
102 | opacity: 0;
103 | }
104 | }
105 |
106 | .serviceListItem:hover {
107 | opacity: 0.8;
108 | .log-EmptyHeart {
109 | opacity: 1;
110 | }
111 | .log-Wheel {
112 | opacity: 1;
113 | }
114 |
115 | .listElementButton {
116 | cursor: pointer;
117 | z-index: 2;
118 | }
119 | }
120 |
121 | .serviceListItem {
122 | margin-left: -$normal-padding;
123 | margin-right: -$normal-padding;
124 |
125 | position: relative;
126 | div & {
127 | @include for-mobile {
128 | margin-left: 0px;
129 | margin-right: 0px;
130 | }
131 | }
132 | }
133 |
134 | .stopedServices {
135 | font-weight: 700;
136 | font-size: $main-font-s;
137 | padding-left: 12px;
138 | }
139 | .stopedServicesBox {
140 | margin-top: 4px;
141 | margin-bottom: 4px;
142 |
143 | .log-Pointer {
144 | font-size: 10px;
145 | cursor: pointer;
146 | padding: 6px;
147 | transform: rotate(0);
148 | &.rotated {
149 | transform: rotate(-90deg);
150 | }
151 | }
152 | }
153 | .buttonBox {
154 | display: flex;
155 | gap: 8px;
156 | }
157 |
158 | .listElementButton {
159 | &:hover {
160 | transform: scale(1.15);
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/LogsSize/LogSize.scss:
--------------------------------------------------------------------------------
1 | .logSizeContainer {
2 | position: relative;
3 | display: flex;
4 | flex-direction: column;
5 | justify-content: space-around;
6 | height: 100%;
7 | color: $text-dark-color;
8 | .log {
9 | font-size: 24px;
10 | }
11 | .title {
12 | margin-top: 10px;
13 | margin-bottom: 10px;
14 | & span {
15 | font-size: 0.7rem;
16 | }
17 | }
18 | .commonText {
19 | color: $text-placeholder-color;
20 | font-size: $main-font-s;
21 | }
22 | .cleanButtonContainer {
23 | position: absolute;
24 | top: 0;
25 | right: 0;
26 | .log {
27 | font-size: 24px !important;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/LogsSize/LogsSize.svelte:
--------------------------------------------------------------------------------
1 |
64 |
65 |
66 |
67 | {#if !isAllLogs}
68 |
76 |
77 | {/if}
78 |
{logsSize} MiB
79 |
{discribeText}
80 |
81 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/LogsString/LogsString.scss:
--------------------------------------------------------------------------------
1 | .logsString {
2 | display: flex;
3 | vertical-align: middle;
4 | align-items: flex-start;
5 | position: relative;
6 | gap: 10px;
7 | padding-bottom: 5px;
8 | padding-top: 5px;
9 | font-family: $mono-font;
10 | font-size: $main-font-s;
11 |
12 | @include for-mobile {
13 | display: block;
14 | line-height: 1.5;
15 |
16 | .message {
17 | // float: left;
18 | display: flex;
19 | flex-direction: column;
20 | }
21 | }
22 |
23 | @include for-tablet {
24 | display: block;
25 | line-height: 1.5;
26 |
27 | .message {
28 | // float: left;
29 | display: flex;
30 | flex-direction: column;
31 | }
32 | }
33 |
34 | .onlogs,
35 | .meta {
36 | color: $active-color;
37 | }
38 |
39 | .status {
40 | vertical-align: middle;
41 | // margin-right: 12px;
42 | min-width: 68px;
43 | line-height: 130%;
44 | cursor: pointer;
45 | & :hover {
46 | transform: scale(1.02);
47 | }
48 |
49 | span {
50 | font-size: 18px;
51 | line-height: 50%;
52 | }
53 |
54 | &.chosenStatus {
55 | background-color: $active-transparent-color;
56 | border-radius: 6px;
57 | }
58 | }
59 |
60 | .time {
61 | width: 84px;
62 | min-width: 101px;
63 | margin-right: 8px;
64 | text-align: center;
65 | display: flex;
66 | @include for-tablet {
67 | margin: 0;
68 | width: 150px;
69 | // display: table-cell;
70 | position: absolute;
71 | left: 80px;
72 | top: 4px;
73 | justify-content: start;
74 | flex-direction: row-reverse;
75 | }
76 | @include for-mobile {
77 | margin: 0;
78 | width: 150px;
79 | // display: table-cell;
80 | position: absolute;
81 | left: 80px;
82 | top: 4px;
83 | justify-content: start;
84 | flex-direction: row-reverse;
85 | }
86 | }
87 |
88 | .shareLinkButtonThumb {
89 | margin-left: 4px;
90 | opacity: 0;
91 | cursor: pointer;
92 | @include for-tablet {
93 | margin: 0 4px 0 0;
94 | }
95 | }
96 |
97 | &:after {
98 | content: "";
99 | width: 100%;
100 | position: absolute;
101 | bottom: 0;
102 |
103 | z-index: 1;
104 | }
105 | .hidden {
106 | opacity: 0;
107 | }
108 | &:last-child {
109 | border-top: solid 1px $lines-color;
110 | }
111 | &.new {
112 | background-color: #4492db2c;
113 | }
114 |
115 | .log-Json {
116 | position: absolute;
117 | left: 12px;
118 | font-size: $main-font-xl;
119 | cursor: pointer;
120 | }
121 | pre {
122 | white-space: pre-wrap;
123 | word-break: break-all;
124 | }
125 | }
126 |
127 | .logsString:hover {
128 | .shareLinkButtonThumb {
129 | opacity: 0.6;
130 | &:hover {
131 | opacity: 1;
132 | }
133 | }
134 | }
135 |
136 | .emptyLogsString {
137 | border-top: none !important;
138 | }
139 |
140 | .number {
141 | color: #f99157;
142 | }
143 |
144 | .string {
145 | color: #be998a;
146 | }
147 |
148 | .key {
149 | color: #6e1963;
150 | }
151 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/LogsString/LogsString.stories.js:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import LogsString from "./LogsString.svelte";
3 | import { action } from "@storybook/addon-actions";
4 | import "../../assets/res/onLogsFont.css";
5 |
6 |
7 |
8 | export default {
9 | component: LogsString,
10 | title: "LogsString",
11 | excludeStories: /.*Data$/,
12 | argTypes: {
13 | status: {
14 | type: "string",
15 | description: "Status of string",
16 | defaultValue: "debug",
17 | options: ["error", "debug", "warn", "info"],
18 | control: { type: "radio" },
19 | },
20 | },
21 |
22 | //👇 The argTypes are included so that they are properly displayed in the Actions Panel
23 | };
24 |
25 | const Template = ({ ...args }) => ({
26 | Component: LogsString,
27 | props: args,
28 |
29 | });
30 |
31 | export const Default = Template.bind({});
32 | Default.args = {
33 | status: "debug",
34 | time: " 16 Jul 07:18:30.683",
35 | message:"starting PostgreSQL 14.0 (Debian 14.0-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit"
36 |
37 | };
38 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/LogsString/LogsString.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
25 | {
27 | if ($chosenStatus !== status) {
28 | chosenStatus.set(status);
29 | } else {
30 | chosenStatus.set("");
31 | }
32 | }}
33 | class="status {status ? status : 'hidden'} {status === $chosenStatus
34 | ? 'chosenStatus'
35 | : ''}"> ◉ {status.toUpperCase()}
37 |
38 | {message?.trim()?.length > 0 ? time : ""}
40 |
41 | {#if message?.trim()?.length > 0}
42 |
{
46 | sharedLinkCallBack();
47 | }}
48 | >
49 |
50 |
{/if}
51 |
52 |
53 |
54 | {#if !parsedStr}
55 | {@html message}
56 |
{:else if $store.transformJson}{parsedStr.startText}
57 | {@html parsedStr.html}
58 | {parsedStr.endText}
59 | {:else}
60 | {@html message}
61 |
{/if}
62 |
63 |
64 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Modal/Modal.scss:
--------------------------------------------------------------------------------
1 | .modalContainer {
2 | // min-width: 40vw;
3 | max-width: 86vw;
4 | // min-width: 40vw;
5 | min-height: min-content;
6 | background-color: $background-color;
7 |
8 | box-shadow: $main-shadow;
9 | padding: $normal-padding;
10 | border-radius: $main-border-radius;
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | transform: translate(-50%, -50%);
15 | z-index: 6;
16 | @include for-mobile {
17 | z-index: 15;
18 | max-width: 96vw;
19 | min-width: 40vw;
20 | .modalContainer {
21 | max-width: 86vw;
22 | min-width: 40vw;
23 | overflow-x: auto;
24 | }
25 | .attentionZone {
26 | width: 86vw;
27 | min-width: 40vw;
28 | overflow-x: auto;
29 | }
30 | }
31 | }
32 |
33 | .closeButton {
34 | color: $active-color;
35 | height: 32px;
36 | width: 32px;
37 | border-radius: 100%;
38 | background-color: rgba(0, 0, 0, 0.1);
39 | display: flex;
40 | align-items: center;
41 | justify-content: center;
42 | position: absolute;
43 | left: calc(100% - 40px);
44 | top: 10px;
45 | cursor: pointer;
46 | }
47 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Modal/Modal.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 | {#if modalIsOpen}
20 | {/if}
29 |
30 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/NotFound/Notfound.scss:
--------------------------------------------------------------------------------
1 | .textContainer {
2 | display: block;
3 | margin-left: auto;
4 | margin-right: auto;
5 | width: fit-content;
6 | margin-top: 30vh;
7 |
8 | .tittle {
9 | margin-bottom: 16px;
10 | }
11 | .linksContainer {
12 | display: flex;
13 | gap: 16px;
14 | justify-content: center;
15 | p {
16 | padding: 8px;
17 | cursor: pointer;
18 | &:hover {
19 | color: $active-color;
20 | background-color: $block-bg-color;
21 | border-radius: $main-border-radius;
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/NotFound/Notfound.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
404 This is not the web page you are looking for...
8 |
9 |
{
11 | navigate(`${changeKey}/`, { replace: true });
12 | }}
13 | >
14 | Move to home page
15 |
16 |
{
18 | navigate(`${changeKey}/404`, { replace: true });
19 | }}
20 | >
21 | Stay here and keep browsing this page
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/OutsideClicker/OutsideClicker.js:
--------------------------------------------------------------------------------
1 | export function clickOutside(node) {
2 | const handleClick = (event) => {
3 | if (node && !node.contains(event.target) && !event.defaultPrevented) {
4 | node.dispatchEvent(new CustomEvent("click_outside", node));
5 | }
6 | };
7 |
8 | document.addEventListener("click", handleClick, true);
9 |
10 | return {
11 | destroy() {
12 | document.removeEventListener("click", handleClick, true);
13 | },
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ProgressBar/ProgressBar.scss:
--------------------------------------------------------------------------------
1 | .progressBarContainer {
2 | width: 100%;
3 | height: 12px;
4 | background-color: $background-color;
5 | border: 2px;
6 | border-radius: 4px;
7 | overflow: hidden;
8 | position: relative;
9 |
10 | .progressBarValue {
11 | height: 12px;
12 | background-color: $active-color;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/ProgressBar/ProgressBar.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/SecretModal/DockerComposeSnippet.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 | example_onlogs:
7 | image: devforth/onlogs
8 | restart: always
9 | environment:
10 | - AGENT=true
11 | - HOST={origin}
12 | - ONLOGS_TOKEN={token}
13 | volumes:
14 | - /var/run/docker.sock:/var/run/docker.sock
15 | - /etc/hostname:/etc/hostname
16 | - onlogs-volume:/leveldb
17 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/SecretModal/DockerSnippet.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | docker run -d --restart always --name onlogs \
8 | -e AGENT=true \
9 | -e HOST={origin} \
10 | -e ONLOGS_TOKEN={token} \
11 | -v /var/run/docker.sock:/var/run/docker.sock:ro \
12 | -v /etc/hostname:/etc/hostname \
13 | -v /var/lib/docker/containers:/var/lib/docker/containers \
14 | -v onlogs-volume:/leveldb \
15 | devforth/onlogs
16 |
17 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/SecretModal/SecretModal.scss:
--------------------------------------------------------------------------------
1 | .secretModalContainer {
2 | background-color: $block-bg-color;
3 | border-radius: $main-border-radius;
4 | padding: $container-padding;
5 | position: absolute;
6 | left: 50%;
7 | top: 50%;
8 | transform: translate(-50%, -50%);
9 | min-height: 200px;
10 | min-width: 300px;
11 | z-index: 7;
12 | display: flex;
13 | flex-direction: column;
14 | .snippetContainer {
15 | min-height: 170px;
16 | min-width: 430px;
17 | background-color: $inpun-color;
18 | border-radius: $main-border-radius;
19 | border-top-left-radius: 0;
20 | box-shadow: $main-shadow;
21 | margin-bottom: 30px;
22 | padding: 20px 16px 20px 16px;
23 | position: relative;
24 |
25 | pre {
26 | color: $text-dark-color;
27 | margin: 0;
28 | }
29 | }
30 | .buttonWrapper {
31 | display: flex;
32 | justify-content: end;
33 | }
34 |
35 | .secretMoalTitle {
36 | color: $text-dark-color;
37 | }
38 |
39 | .labelsBox {
40 | justify-content: left;
41 | max-width: 50%;
42 | max-height: 70px;
43 | box-shadow: $main-shadow;
44 | margin-top: $container-padding;
45 | align-items: stretch;
46 |
47 | font-size: $main-font-xs;
48 | }
49 | .labelItem {
50 | padding: 6px;
51 | width: 50%;
52 | border-top-right-radius: 4px;
53 | border-top-left-radius: 4px;
54 | margin-right: 4px;
55 |
56 | background-color: $inpun-color-dark;
57 | &.active {
58 | z-index: 5;
59 | }
60 | &.active {
61 | color: $active-color;
62 | font-weight: 600;
63 | }
64 | }
65 |
66 | .coppyButton {
67 | position: absolute;
68 | top: 14px;
69 | right: 14px;
70 | i {
71 | font-size: 18px !important;
72 | }
73 | }
74 | @include for-mobile {
75 | z-index: 15;
76 | max-width: 86vw;
77 | .snippetContainer {
78 | max-width: 76vw;
79 | min-width: 60vw;
80 | overflow-x: auto;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/SecretModal/SecretModal.svelte:
--------------------------------------------------------------------------------
1 |
40 |
41 | {
45 | snipetModalIsVisible.set(false);
46 | }}
47 | >
48 |
Connect new host
49 |
50 |
{
55 | choseSnippetOption("Docker");
56 | }}
57 | >
58 | Docker
59 |
60 |
{
65 | choseSnippetOption("DockerCompose");
66 | }}
67 | >
68 | Docker Compose
69 |
70 |
71 |
72 | {#if $currentSnippedOption === "Docker"}
73 |
74 | {/if}
75 | {#if $currentSnippedOption === "DockerCompose"}
76 |
77 | {/if}
78 |
79 | {
85 | copyText(document.querySelector("pre"), () => {
86 | toast.set({
87 | tittle: "Success",
88 | message: "Text has been copied",
89 | position: "",
90 | status: "Success",
91 | });
92 | toastIsVisible.set(true);
93 | setTimeout(() => {
94 | toastIsVisible.set(false);
95 | }, 5000);
96 | });
97 | }}
98 | />
99 |
100 |
101 |
102 | {
107 | snipetModalIsVisible.set(false);
108 | addHostMenuIsVisible;
109 | }}
110 | />
111 |
112 |
113 |
114 | {
116 | handleKeydown(e, "Escape", () => {
117 | snipetModalIsVisible.set(false);
118 | });
119 | }}
120 | />
121 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Stats/Stats.scss:
--------------------------------------------------------------------------------
1 | .statsItem {
2 | padding: 0;
3 | margin: 0 0 6px 0;
4 | font-size: $main-font-s;
5 | cursor: pointer;
6 | & :hover {
7 | transform: scale(1.02);
8 | }
9 | }
10 |
11 | .statsTittle {
12 | margin-top: 12px;
13 | margin-bottom: 12px;
14 | }
15 |
16 | .log-Info {
17 | font-size: 18px;
18 | line-height: 1;
19 | }
20 | .timeSpan {
21 | font-size: $main-font-s;
22 | & div {
23 | padding: 2px;
24 | font-weight: 600;
25 | cursor: pointer;
26 | &.active {
27 | color: $active-color;
28 | }
29 | }
30 | }
31 |
32 | .statsContainer {
33 | color: $text-dark-color;
34 | }
35 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Stats/Stats.svelte:
--------------------------------------------------------------------------------
1 |
50 |
51 |
52 |
53 |
{
56 | // navigate(
57 | // `${changeKey}/stats/${$lastChosenHost}/${$lastChosenService}`,
58 | // {
59 | // replace: true,
60 | // }
61 | // );
62 | }}
63 | title="Counter updates every 1 min since OnLogs started. So, it may cause some asynchrony."
64 | />
65 |
66 |
{
69 | setPeriod(2);
70 | }}
71 | >
72 | 1hr
73 |
74 |
{
77 | setPeriod(48);
78 | }}
79 | >
80 | 1d
81 |
82 |
{
85 | setPeriod(336);
86 | }}
87 | >
88 | 1w
89 |
90 |
{
93 | setPeriod(1344);
94 | }}
95 | >
96 | 1m
97 |
98 |
99 |
100 |
101 | Top {Object.keys(data).length ? Object.keys(data).length : ""} levels:
102 |
103 |
125 |
126 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/StreamInfo/StreamInfo.scss:
--------------------------------------------------------------------------------
1 | .log-Last {
2 | font-size: 20px;
3 | color: $active-color;
4 | cursor: pointer;
5 | }
6 |
7 | .log-container {
8 | display: flex;
9 | flex-direction: column;
10 | gap: 8px;
11 |
12 | .log-Last {
13 | margin-right: 8px;
14 | &.WSisMuted {
15 | color: rgba(0, 0, 0, 0.151);
16 | }
17 | }
18 |
19 | .log-time {
20 | display: flex;
21 | align-items: center;
22 |
23 | span {
24 | margin-left: 4px;
25 | }
26 | }
27 |
28 | .log-time-ago {
29 | }
30 | }
31 | .streamInfoTimeWrapper {
32 | display: flex;
33 | gap: 4px;
34 | align-items: baseline;
35 | }
36 |
37 | .streamInfoTime {
38 | font-size: $main-font-m;
39 | font-weight: 700;
40 | }
41 |
42 | .streamInfoTimeShortName {
43 | vertical-align: bottom;
44 | line-height: 1;
45 | font-size: 0.8rem;
46 | }
47 | .log-heading {
48 | font-size: $main-font-s;
49 | font-weight: 200;
50 | }
51 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/StreamInfo/StreamInfo.svelte:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
{
33 | if ($WSisMuted) {
34 | WSisMuted.set(false);
35 | manuallyUnmuted.set(true);
36 | } else {
37 | WSisMuted.set(true);
38 | manuallyUnmuted.set(false);
39 | }
40 | }}
41 | />
42 |
43 | Last log line:
44 | {#if Array.isArray(componentLastLogTime)}
45 | {#if componentLastLogTime?.at(0)[0] || componentLastLogTime?.at(1)[0]}
46 |
47 | {#each componentLastLogTime as e}
48 | {#if e?.at(0)}
49 | {e?.at(0)}
50 |
51 | {e?.at(1)} {/if}
52 | {/each}
53 |
54 | {/if}
55 | {#if componentLastLogTime?.at(0)[0] === 0 && componentLastLogTime?.at(1)[0] === 0}
56 | Recently
57 | {/if}
58 | {#if componentLastLogTime?.at(0) === "" && componentLastLogTime?.at(1) === ""}
59 | No logs
60 | {/if}
61 | {/if}
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Toast/Toast.scss:
--------------------------------------------------------------------------------
1 | .toastContainer {
2 | width: 300px;
3 | height: 140px;
4 | position: absolute;
5 | top: 20px;
6 | left: 50%;
7 | transform: translate(-50%);
8 | display: flex;
9 | flex-direction: column;
10 | align-items: center;
11 | padding: 0 12px 0 12px;
12 |
13 | border-radius: $main-border-radius;
14 | box-shadow: $main-shadow;
15 | box-sizing: border-box;
16 | z-index: 10;
17 | color: #ffffff;
18 |
19 | background-color: $block-bg-color;
20 |
21 | .toastButtonContainer {
22 | max-height: 64px;
23 | position: absolute;
24 | bottom: 12px;
25 | right: 12px;
26 | &.additionalButton {
27 | left: 12px;
28 | }
29 | }
30 |
31 | .log {
32 | font-size: $main-font-l;
33 | position: absolute;
34 | left: 12px;
35 | top: 12px;
36 | &-Error {
37 | color: #992c2c;
38 | }
39 |
40 | &-Success {
41 | color: #2f912d;
42 | }
43 |
44 | &-Warning {
45 | color: #ac681a;
46 | }
47 | }
48 |
49 | p {
50 | overflow: hidden;
51 | text-overflow: ellipsis;
52 | color: $text-dark-color;
53 | margin-bottom: 12px;
54 | font-size: $main-font-s;
55 | }
56 | h4 {
57 | margin: 12px 0 12px 0;
58 | color: $text-dark-color;
59 | font-size: $main-font-l;
60 | }
61 |
62 | .additionButtonContainer {
63 | display: flex;
64 | justify-content: space-between;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/Toast/Toast.svelte:
--------------------------------------------------------------------------------
1 |
20 |
21 |
25 |
26 |
{tittle}
27 |
{message}
28 |
29 |
30 |
55 |
56 |
57 | {
59 | handleKeydown(e, "Escape", () => {
60 | toastIsVisible.set(false);
61 | if (toastTimeoutId) {
62 | clearTimeout($toastTimeoutId);
63 | }
64 | });
65 | }}
66 | />
67 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/UserMenu/UserManageForm.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
49 |
--------------------------------------------------------------------------------
/application/frontend/src/lib/UserMenu/UserMenu.scss:
--------------------------------------------------------------------------------
1 | .userTable {
2 | width: 100%;
3 |
4 | th {
5 | padding: 5px;
6 | border-bottom: 1px solid $lines-color;
7 | }
8 | tr {
9 | border-bottom: 1px solid $lines-color;
10 | }
11 |
12 | span {
13 | display: flex;
14 | align-items: center;
15 | justify-content: center;
16 | padding: 12px;
17 | }
18 | .buttonSpanContainer {
19 | max-width: 150px;
20 | margin-left: auto;
21 | margin-right: 16px;
22 | padding: 4px;
23 | }
24 | .buttonSpan {
25 | padding: 0;
26 | margin-left: 12px;
27 | }
28 | }
29 |
30 | table {
31 | border-collapse: collapse;
32 | }
33 |
34 | .userCreateForm {
35 | color: $lines-color;
36 |
37 | .input {
38 | padding: $normal-padding;
39 | background-color: $inpun-color;
40 | border-radius: $main-border-radius;
41 | border: 1px solid $lines-color;
42 | width: 100%;
43 | outline: none;
44 | box-sizing: border-box;
45 | }
46 | label {
47 | margin-bottom: 6px;
48 | font-size: $main-font-s;
49 | color: $text-dark-color;
50 | margin-left: 6px;
51 | }
52 |
53 | .inputContainer {
54 | display: flex;
55 | flex-direction: column;
56 | margin-top: 12px;
57 | justify-content: center;
58 | align-items: center;
59 | }
60 |
61 | input:focus {
62 | border: 2px solid $active-color;
63 | }
64 |
65 | .buttonsContainer {
66 | display: flex;
67 | justify-content: center;
68 | margin-top: 24px;
69 | gap: 42px;
70 | }
71 |
72 | h3 {
73 | color: $text-dark-color;
74 | }
75 | }
76 |
77 | .usersHeaderContainer {
78 | display: flex;
79 | justify-content: space-between;
80 | gap: 24px;
81 | align-items: center;
82 | h3 {
83 | max-width: 150px;
84 | }
85 | .addUserButton {
86 | padding: 12px;
87 | width: 20px;
88 | height: 20px;
89 | border-radius: 100%;
90 | display: flex;
91 | align-items: center;
92 | justify-content: center;
93 | cursor: pointer;
94 | background-color: $active-color;
95 | color: $text-onactive-color;
96 | }
97 | .addUserButton:hover {
98 | transform: scale(1.1);
99 | }
100 | }
101 |
102 | .buttonModalContainer {
103 | display: flex;
104 | margin-top: 54px;
105 | margin-bottom: 24px;
106 | justify-content: space-around;
107 | }
108 |
109 | .editInput {
110 | border-radius: 10px;
111 | padding: 6px 12px;
112 | box-sizing: border-box;
113 | font-size: $main-font-m;
114 | border: 1px solid $lines-color;
115 | margin-top: 20px;
116 |
117 | border: 1px solid $text-placeholder-color;
118 | color: $text-dark-color;
119 |
120 | &:focus {
121 | outline: none;
122 | border: 2px solid $active-color;
123 | // caret-color: transparent;
124 | }
125 | }
126 | .editInputContainer {
127 | display: flex;
128 | justify-content: center;
129 | }
130 | .userMenu {
131 | text-align: center;
132 | }
133 |
--------------------------------------------------------------------------------
/application/frontend/src/main.js:
--------------------------------------------------------------------------------
1 | import "./main.scss";
2 | import App from "./App.svelte";
3 | import "@/assets/res/onLogsFont.css";
4 |
5 | const app = new App({
6 | target: document.getElementById("app"),
7 | });
8 |
9 | export default app;
10 |
--------------------------------------------------------------------------------
/application/frontend/src/main.scss:
--------------------------------------------------------------------------------
1 | @import "./utils/variables";
2 | @import "./Views/Main/Main.scss";
3 | @import "./lib/Button/Button.scss";
4 | @import "./lib/Container/Container.scss";
5 | @import "./lib/LogsString/LogsString.scss";
6 |
7 | @import "./Views/Logs/LogsView.scss";
8 | @import "./Views/Login//Login.scss";
9 | @import "./lib/HostList/HostList.scss";
10 | @import "./lib/ClientPanel/ClientPanel.scss";
11 | @import "./lib/DropDown/DropDown.scss";
12 | @import "./lib/CheckBox/CheckBox.scss";
13 | @import "./lib/UserMenu/UserMenu.scss";
14 | @import "./lib/Modal/Modal.scss";
15 | @import "./Theme.scss";
16 | @import "./lib/ListWithChoise/ListWithChoise.scss";
17 | @import "./lib/CommonList/CommonList.scss";
18 | @import "./lib/ButtonToBottom/ButtonToBottom.scss";
19 | @import "./lib/Toast/Toast.scss";
20 | @import "./lib/NotFound/Notfound.scss";
21 | @import "./lib/SecretModal/SecretModal.scss";
22 | @import "./lib/LogsSize/LogSize.scss";
23 | @import "./lib/ConfirmationMenu/ConfirmationMenu.scss";
24 | @import "./Views/ServiceSettings/ServiceSettings.scss";
25 | @import "./lib/Stats/Stats.scss";
26 | @import "./lib/ChartMenu/ChartMenu.scss";
27 | @import "./lib/ProgressBar/ProgressBar.scss";
28 | @import "./lib/StreamInfo/StreamInfo.scss";
29 | body {
30 | font-family: "Ubuntu", sans-serif;
31 | background-color: $background-color;
32 | height: 100vh;
33 | width: 100vw;
34 | margin: 0;
35 | }
36 |
37 | h1,
38 | h2,
39 | h3,
40 | h4 {
41 | margin: 0;
42 | }
43 | h1 {
44 | font-size: $main-font-xl;
45 | }
46 |
47 | .contentContainer {
48 | padding: $normal-padding;
49 | box-sizing: border-box;
50 | height: 100vh;
51 | }
52 |
53 | li {
54 | list-style: none;
55 | color: inherit;
56 | }
57 |
58 | p {
59 | margin: 0;
60 | }
61 |
62 | button {
63 | border-width: 0px;
64 | }
65 |
66 | ul {
67 | padding: 0;
68 | margin: 0;
69 | }
70 |
71 | h2 {
72 | padding: 0;
73 | margin: 0;
74 | }
75 |
76 | input {
77 | border: 0;
78 | }
79 |
80 | .visuallyHidden {
81 | position: absolute;
82 | left: -999999px;
83 | top: -999999px;
84 | width: 1px;
85 | height: 1px;
86 | display: none;
87 | opacity: 0;
88 | }
89 |
90 | .clickable {
91 | cursor: pointer;
92 | }
93 |
94 | .modalOverlay {
95 | position: absolute;
96 | height: 100%;
97 | width: 100%;
98 | background-color: rgba(0, 0, 0, 0.4);
99 | top: 0;
100 | left: 0;
101 | z-index: 6;
102 | }
103 |
104 | @include for-mobile {
105 | #modalOverlay {
106 | z-index: 14;
107 | }
108 | }
109 |
110 | ::-webkit-scrollbar-thumb {
111 | background-color: #00000020;
112 | border-radius: 10px;
113 | }
114 | .error {
115 | color: #ff4242;
116 | }
117 |
118 | .debug {
119 | color: #178f15;
120 | }
121 |
122 | .warn {
123 | color: #ff8a00;
124 | }
125 |
126 | .info {
127 | color: skyblue;
128 | }
129 |
130 | .meta {
131 | color: #4e49da;
132 | }
133 |
134 | li {
135 | cursor: default;
136 | }
137 |
--------------------------------------------------------------------------------
/application/frontend/src/utils/_variables.scss:
--------------------------------------------------------------------------------
1 | // colors
2 | $active-color: #4e49da;
3 | $inpun-color: #f8fafb;
4 | $text-onactive-color: #fbfcff;
5 | $text-dark-color: #1b1850;
6 | $text-placeholder-color: #a3a3b9;
7 | $lines-color: #c8d2e5;
8 | $background-color: #eaf0f7d7;
9 | $btn-common-color: #414860;
10 | $btn-primary-color: #ffffff;
11 | $block-bg-color: #ffffff;
12 | $active-transparent-color: #4e49da40;
13 |
14 | $active-color-dark: #c244db;
15 | $inpun-color-dark: #99a9b931;
16 | $text-onactive-color-dark: #e4e7eb;
17 | $text-dark-color-dark: #cbd2d9;
18 | $text-placeholder-color-dark: #e4e7eb;
19 | $lines-color-dark: #cbd2d9;
20 | $background-color-dark: #121212;
21 | $btn-primary-color-dark: #c244db;
22 | $lines-color-dark: #cbd2d938;
23 | $inputs-border-color: #ffffff00;
24 | $active-transparent-color-dark: #c244db40;
25 |
26 | $block-bg-color-dark: #1f2933;
27 | $mono-font: "Source Code Pro", monospace;
28 | // shadows
29 |
30 | $main-shadow: 1px 1px 10px rgba(0, 0, 0, 0.15);
31 | $container-shadow: 1px 1px 30px rgba(5, 39, 70, 0.1);
32 |
33 | $main-shadow-dark: 1px 1px 5px rgba(0, 0, 0, 0.7);
34 | $container-shadow-dark: 1px 1px 12px rgba(23, 24, 24, 0.7);
35 |
36 | //border-radius
37 |
38 | $main-border-radius: 10px;
39 | $large-border-radius: 20px;
40 |
41 | //fonts
42 | $main-font-xs: 12px;
43 | $main-font-s: 14px;
44 | $main-font-m: 16px;
45 | $main-font-l: 22px;
46 | $main-font-xl: 28px;
47 |
48 | //line-height
49 | $line-height: 2.5;
50 |
51 | //paddings
52 | $normal-padding: 12px;
53 | $container-padding: 12px;
54 | $container-vertical-padding: 16px;
55 |
56 | //mixins
57 | @mixin hide {
58 | position: absolute;
59 | opacity: 0;
60 | left: -99999px;
61 | right: -99999px;
62 | height: 1px;
63 | width: 1px;
64 | }
65 | @mixin visible {
66 | position: static;
67 | opacity: 1;
68 | left: 0px;
69 | right: 0px;
70 | height: auto;
71 | width: auto;
72 | }
73 |
74 | @mixin for-mobile {
75 | @media (min-width: 200px) and (max-width: 750px) {
76 | @content;
77 | }
78 | }
79 |
80 | @mixin for-tablet {
81 | @media (min-width: 750px) and (max-width: 1150px) {
82 | @content;
83 | }
84 | }
85 |
86 | @mixin for-desctop {
87 | @media (min-width: 950px) {
88 | @content;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/application/frontend/src/utils/changeKey.js:
--------------------------------------------------------------------------------
1 | export const changeKey = location.href.includes("localhost:5173")
2 | ? ""
3 | : "/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION";
4 |
--------------------------------------------------------------------------------
/application/frontend/src/utils/functions.js:
--------------------------------------------------------------------------------
1 | import json2html from "json-to-html";
2 |
3 | export const handleKeydown = (e, keyValue, cb) => {
4 | if (e.key === keyValue) {
5 | cb();
6 | }
7 | };
8 |
9 | export const emulateData = (amount) => {
10 | const randomArray = (length, max) =>
11 | [...new Array(length)].map(() => Math.round(Math.random() * max));
12 |
13 | let data = {
14 | dates: new Array(amount).fill("1"),
15 | debug: randomArray(10, 1000),
16 | error: randomArray(10, 1000),
17 | info: randomArray(10, 1000),
18 | warn: randomArray(10, 1000),
19 | other: randomArray(10, 1000),
20 | };
21 | return data;
22 | };
23 |
24 | export const tryToParseLogString = (str) => {
25 | const beginningOfJson = str.indexOf("{");
26 | const endingOfJson = str.lastIndexOf("}");
27 |
28 | let html = "";
29 | let startText = "";
30 | let endText = "";
31 |
32 | if (beginningOfJson !== -1 && endingOfJson !== -1) {
33 | if (endingOfJson > beginningOfJson) {
34 | const jsonPart = str.slice(beginningOfJson, endingOfJson);
35 | startText = str.slice(0, beginningOfJson);
36 | endText = str.slice(endingOfJson + 1, -1);
37 | try {
38 | let normilizedStr = JSON.parse(jsonPart + "}");
39 | html = json2html(normilizedStr, 2);
40 | } catch (e) {}
41 | }
42 | }
43 |
44 | if (html) {
45 | return { startText, html, endText };
46 | } else return null;
47 | };
48 |
49 | export const copyText = function (ref, cb) {
50 | const text = ref;
51 | let textToCopy = text.innerText;
52 | if (navigator.clipboard) {
53 | navigator.clipboard.writeText(textToCopy).then(() => {
54 | cb();
55 | });
56 | } else {
57 | console.log("Browser Not compatible");
58 | }
59 | };
60 |
61 | export const copyCustomText = function (text, cb) {
62 | let textToCopy = text;
63 | if (navigator.clipboard) {
64 | navigator.clipboard.writeText(textToCopy).then(() => {
65 | cb();
66 | });
67 | } else {
68 | console.log("Browser Not compatible");
69 | }
70 | };
71 |
72 | export function getTimeDifference(t) {
73 | const now = Date.now();
74 | const timestamp = Date.parse(t);
75 | const difference = Math.abs(now - timestamp) / 1000; // difference in seconds
76 |
77 | const hours = Math.floor((difference % 86400) / 3600);
78 | const minutes = Math.floor((difference % 3600) / 60);
79 |
80 | function showIfExisted(v, time) {
81 | if (v || v === 0) {
82 | return [v, time];
83 | }
84 | return "";
85 | }
86 |
87 | return [showIfExisted(hours, "h"), showIfExisted(minutes, "m")];
88 | }
89 |
--------------------------------------------------------------------------------
/application/frontend/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/application/frontend/startDebug.js:
--------------------------------------------------------------------------------
1 | import fs from "fs-extra";
2 |
3 | const srcDir = `./dist`;
4 | const destDir = `../backend/dist`;
5 |
6 | // To copy a folder or file, select overwrite accordingly
7 | try {
8 | fs.copySync(srcDir, destDir, { overwrite: true });
9 | console.log("success!");
10 | } catch (err) {
11 | console.error(err);
12 | }
13 |
--------------------------------------------------------------------------------
/application/frontend/storybook-static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devforth/OnLogs/21983bae44c52a347f7d9ef03cabfe636aef0bee/application/frontend/storybook-static/favicon.ico
--------------------------------------------------------------------------------
/application/frontend/storybook-static/project.json:
--------------------------------------------------------------------------------
1 | {"generatedAt":1670422110895,"builder":{"name":"@storybook/builder-vite"},"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"features":{"storyStoreV7":true},"storybookVersion":"6.5.13","language":"javascript","storybookPackages":{"@storybook/addon-actions":{"version":"6.5.13"},"@storybook/builder-vite":{"version":"0.2.5"},"@storybook/svelte":{"version":"6.5.13"},"@storybook/testing-library":{"version":"0.0.13"}},"framework":{"name":"svelte"},"addons":{"@storybook/addon-links":{"version":"6.5.12"},"@storybook/addon-essentials":{"version":"6.5.13"},"@storybook/addon-interactions":{"version":"6.5.12"}}}
2 |
--------------------------------------------------------------------------------
/application/frontend/storybook-static/stories.json:
--------------------------------------------------------------------------------
1 | {"v":3,"stories":{"button--default":{"id":"button--default","title":"Button","name":"Default","importPath":"./src/lib/Button/Button.stories.js"},"container--default":{"id":"container--default","title":"Container","name":"Default","importPath":"./src/lib/Container/Container.stories.js"},"logsstring--default":{"id":"logsstring--default","title":"LogsString","name":"Default","importPath":"./src/lib/LogsString/LogsString.stories.js"}}}
2 |
--------------------------------------------------------------------------------
/application/frontend/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig, loadEnv } from "vite";
2 | import { svelte } from "@sveltejs/vite-plugin-svelte";
3 | import * as path from "path";
4 | const VITE_ASSET_URL = import.meta.VITE_ASSET_URL || "";
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | resolve: {
8 | alias: {
9 | "@": path.resolve(__dirname, "src"),
10 | },
11 | },
12 | plugins: [svelte({})],
13 | });
14 |
--------------------------------------------------------------------------------
/application/release.sh:
--------------------------------------------------------------------------------
1 | # docker buildx create --use
2 | docker buildx build --platform=linux/amd64,linux/arm64 --tag "devforth/onlogs:latest" --tag "devforth/onlogs:1.1.6" --push .
3 | # docker run -v /var/run/docker.sock:/var/run/docker.sock --rm -it $(docker build -q -f Dockerfile .)
4 | # docker build . -t devforth/onlogs && docker push devforth/onlogs
5 |
--------------------------------------------------------------------------------