Changelog: https://roxy-wi.org/changelog#7.0.2
pull/372/head
Aidaho 2023-11-02 15:38:04 +03:00
parent a2581227b5
commit 62071588e9
25 changed files with 933 additions and 182 deletions

View File

@ -668,7 +668,7 @@ def update_db_v_6_3_18():
def update_ver():
try:
Version.update(version='7.0.1.0').execute()
Version.update(version='7.0.2.0').execute()
except Exception:
print('Cannot update version')

View File

@ -12,7 +12,10 @@ import app.modules.roxy_wi_tools as roxy_wi_tools
@app.before_request
@cache.memoize(3)
def check_login():
if request.endpoint not in ('login_page', 'static', 'main.show_roxywi_version', 'service.check_service'):
if request.endpoint not in (
'login_page', 'static', 'main.show_roxywi_version', 'service.check_service', 'smon.show_smon_status_page',
'smon.smon_history_statuses'
):
try:
user_params = roxywi_common.get_users_params()
except Exception:

View File

@ -357,6 +357,8 @@ def delete_ip_from_list(serv, ip_id, ip, list_id, list_name) -> str:
except Exception:
pass
return 'ok'
def add_ip_to_list(serv, ip, list_id, list_name) -> str:
haproxy_sock_port = sql.get_setting('haproxy_sock_port')
@ -371,13 +373,12 @@ def add_ip_to_list(serv, ip, list_id, list_name) -> str:
pass
try:
if stderr:
print(f'error: {stderr[0]}')
return f'error: {stderr[0]}'
except Exception:
pass
if 'is not a valid IPv4 or IPv6 address' not in output[0]:
cmd = f'echo "{ip}" >> {lib_path}/lists/{user_group}/{list_name}'
print(cmd)
output, stderr = server_mod.subprocess_execute(cmd)
roxywi_common.logging(serv, f'{ip} has been added to list {list_id}', login=1, keep_history=1, service='haproxy')
if output:

View File

@ -616,6 +616,26 @@ class SmonDnsCheck(BaseModel):
primary_key = False
class SmonStatusPage(BaseModel):
id = AutoField()
name = CharField()
slug = CharField(unique=True)
desc = CharField(null=True)
group_id = IntegerField()
class Meta:
table_name = 'smon_status_pages'
class SmonStatusPageCheck(BaseModel):
page_id = ForeignKeyField(SmonStatusPage, on_delete='Cascade')
check_id = ForeignKeyField(SMON, on_delete='Cascade')
class Meta:
table_name = 'smon_status_page_checks'
primary_key = False
class RoxyTool(BaseModel):
id = AutoField()
name = CharField()
@ -636,4 +656,5 @@ def create_tables():
PortScannerSettings, PortScannerPorts, PortScannerHistory, ServiceSetting, MetricsHttpStatus,
SMON, WafRules, Alerts, GeoipCodes, NginxMetrics, SystemInfo, Services, UserName, GitSetting,
CheckerSetting, ApacheMetrics, WafNginx, ServiceStatus, KeepaliveRestart, PD, SmonHistory,
SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup, RoxyTool])
SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup, RoxyTool, SmonStatusPage,
SmonStatusPageCheck])

View File

@ -781,6 +781,9 @@ def get_user_id_by_uuid(uuid):
else:
for user in query_res:
return user.user_id
finally:
if not conn.is_closed():
conn.close()
def get_user_id_by_username(username: str):
@ -3032,10 +3035,9 @@ def insert_smon_history(smon_id: int, response_time: float, status: int, check_i
conn.close()
def select_smon_history(smon_id: int, check_id: int) -> object:
def select_smon_history(smon_id: int) -> object:
query = SmonHistory.select().where(
(SmonHistory.smon_id == smon_id) &
(SmonHistory.check_id == check_id)
SmonHistory.smon_id == smon_id
).limit(40).order_by(SmonHistory.date.desc())
try:
query_res = query.execute()
@ -3045,10 +3047,9 @@ def select_smon_history(smon_id: int, check_id: int) -> object:
return query_res
def get_last_smon_status_by_check(smon_id: int, check_id: int) -> object:
def get_last_smon_status_by_check(smon_id: int) -> object:
query = SmonHistory.select().where(
(SmonHistory.smon_id == smon_id) &
(SmonHistory.check_id == check_id)
SmonHistory.smon_id == smon_id
).limit(1).order_by(SmonHistory.date.desc())
try:
query_res = query.execute()
@ -3079,11 +3080,10 @@ def get_last_smon_res_time_by_check(smon_id: int, check_id: int) -> object:
return ''
def get_smon_history_count_checks(smon_id: int, check_id: int) -> dict:
def get_smon_history_count_checks(smon_id: int) -> dict:
count_checks = {}
query = SmonHistory.select(fn.Count(SmonHistory.status)).where(
(SmonHistory.smon_id == smon_id) &
(SmonHistory.check_id == check_id)
SmonHistory.smon_id == smon_id
)
try:
query_res = query.execute()
@ -3098,7 +3098,6 @@ def get_smon_history_count_checks(smon_id: int, check_id: int) -> dict:
query = SmonHistory.select(fn.Count(SmonHistory.status)).where(
(SmonHistory.smon_id == smon_id) &
(SmonHistory.check_id == check_id) &
(SmonHistory.status == 1)
)
try:
@ -4191,3 +4190,63 @@ def get_tool_cur_version(tool_name: str):
out_error(e)
else:
return query
def add_status_page(name: str, slug: str, desc: str, group_id: int, checks: list) -> int:
try:
last_id = SmonStatusPage.insert(name=name, slug=slug, group_id=group_id, desc=desc).execute()
except Exception as e:
if '1062, "Duplicate entry' in str(e):
raise Exception('error: The Slug is already taken, please enter another one')
else:
out_error(e)
else:
for check in checks:
try:
SmonStatusPageCheck.insert(page_id=last_id, check_id=int(check)).execute()
except Exception as e:
out_error(e)
return last_id
def select_status_pages(group_id: int):
try:
query_res = SmonStatusPage.select().where(SmonStatusPage.group_id == group_id).execute()
except Exception as e:
return out_error(e)
else:
return query_res
def select_status_page_by_id(page_id: int):
try:
query_res = SmonStatusPage.select().where(SmonStatusPage.id == page_id).execute()
except Exception as e:
return out_error(e)
else:
return query_res
def select_status_page(slug: str):
try:
query_res = SmonStatusPage.select().where(SmonStatusPage.slug == slug).execute()
except Exception as e:
out_error(e)
else:
return query_res
def select_status_page_checks(page_id: int):
try:
query_res = SmonStatusPageCheck.select().where(SmonStatusPageCheck.page_id == page_id).execute()
except Exception as e:
out_error(e)
else:
return query_res
def delete_status_page(page_id):
try:
SmonStatusPage.delete().where(SmonStatusPage.id == page_id).execute()
except Exception as e:
out_error(e)

View File

@ -32,8 +32,6 @@ def versions():
current_ver_without_dots = current_ver.split('.')
current_ver_without_dots = ''.join(current_ver_without_dots)
current_ver_without_dots = current_ver_without_dots.replace('\n', '')
if len(current_ver_without_dots) == 4:
current_ver_without_dots += '0'
current_ver_without_dots = int(current_ver_without_dots)
except Exception:
current_ver = "Cannot get current version"

View File

@ -1,4 +1,4 @@
from flask import render_template
from flask import render_template, abort
import modules.db.sql as sql
import modules.roxywi.common as roxywi_common
@ -90,8 +90,8 @@ def delete_smon(smon_id, user_group) -> str:
raise Exception(f'error: Cannot delete the server {e}')
def history_metrics(server_id: int, check_id: int) -> dict:
metric = sql.select_smon_history(server_id, check_id)
def history_metrics(server_id: int) -> dict:
metric = sql.select_smon_history(server_id)
metrics = {'chartData': {}}
metrics['chartData']['labels'] = {}
@ -108,14 +108,14 @@ def history_metrics(server_id: int, check_id: int) -> dict:
return metrics
def history_statuses(dashboard_id: int, check_id: int) -> None:
smon_statuses = sql.select_smon_history(dashboard_id, check_id)
def history_statuses(dashboard_id: int) -> None:
smon_statuses = sql.select_smon_history(dashboard_id)
return render_template('ajax/smon/history_status.html', smon_statuses=smon_statuses)
def history_cur_status(dashboard_id: int, check_id: int) -> None:
cur_status = sql.get_last_smon_status_by_check(dashboard_id, check_id)
cur_status = sql.get_last_smon_status_by_check(dashboard_id)
smon = sql.select_one_smon(dashboard_id, check_id)
return render_template('ajax/smon/cur_status.html', cur_status=cur_status, smon=smon)
@ -126,3 +126,48 @@ def return_smon_status():
smon_status, stderr = server_mod.subprocess_execute(cmd)
return smon_status, stderr
def check_uptime(smon_id: int) -> int:
count_checks = sql.get_smon_history_count_checks(smon_id)
try:
uptime = round(count_checks['up'] * 100 / count_checks['total'], 2)
except Exception:
uptime = 0
return uptime
def create_status_page(name: str, slug: str, desc: str, checks: list) -> str:
group_id = roxywi_common.get_user_group(id=1)
try:
page_id = sql.add_status_page(name, slug, desc, group_id, checks)
except Exception as e:
raise Exception(f'{e}')
pages = sql.select_status_page_by_id(page_id)
return render_template('ajax/smon/status_pages.html', pages=pages)
def show_status_page(slug: str) -> str:
page = sql.select_status_page(slug)
checks_status = {}
if not page:
abort(404, 'Not found status page')
for p in page:
page_id = p.id
checks = sql.select_status_page_checks(page_id)
for check in checks:
check_id = str(check.check_id)
smon_name = sql.get_smon_service_name_by_id(check_id)
uptime = check_uptime(check_id)
checks_status[check_id] = {'uptime': uptime, 'name': smon_name}
return render_template('smon/status_page.html', page=page, checks_status=checks_status)

View File

@ -1,7 +1,6 @@
from flask import render_template, g
from flask_login import login_required
from app import cache
from app.routes.overview import bp
from middleware import get_user_params
import app.modules.db.sql as sql
@ -45,7 +44,6 @@ def overview_users():
@bp.route('/overview/sub')
@cache.cached()
def overview_sub():
return roxy_overview.show_sub_ovw()

View File

@ -79,13 +79,17 @@ def change_settings_portscanner():
return 'ok'
@bp.route('/scan/<int:server_id>')
def scan_port(server_id):
server = sql.select_servers(id=server_id)
ip = ''
@bp.route('/scan/<int:server_id>', defaults={'server_ip': None})
@bp.route('/scan/<server_ip>', defaults={'server_id': None})
def scan_port(server_id, server_ip):
if server_ip:
ip = server_ip
else:
server = sql.select_servers(id=server_id)
ip = ''
for s in server:
ip = s[2]
for s in server:
ip = s[2]
cmd = f"sudo nmap -sS {ip} |grep -E '^[[:digit:]]'|sed 's/ */ /g'"
cmd1 = f"sudo nmap -sS {ip} |head -5|tail -2"

View File

@ -1,3 +1,4 @@
import json
from pytz import timezone
from flask import render_template, request, jsonify, g
from flask_login import login_required
@ -12,14 +13,8 @@ import app.modules.roxywi.common as roxywi_common
import app.modules.tools.smon as smon_mod
@bp.before_request
@login_required
def before_request():
""" Protect all of the admin endpoints. """
pass
@bp.route('/dashboard')
@login_required
@get_user_params()
def smon():
roxywi_common.check_user_group_for_flask()
@ -38,6 +33,7 @@ def smon():
@bp.route('/dashboard/<dashboard_id>/<check_id>')
@login_required
@get_user_params()
def smon_dashboard(dashboard_id, check_id):
user_params = g.user_params
@ -51,12 +47,8 @@ def smon_dashboard(dashboard_id, check_id):
present = present.strftime('%b %d %H:%M:%S %Y %Z')
present = datetime.strptime(present, '%b %d %H:%M:%S %Y %Z')
cert_day_diff = 'N/A'
count_checks = sql.get_smon_history_count_checks(dashboard_id, check_id)
uptime = smon_mod.check_uptime(dashboard_id)
try:
uptime = round(count_checks['up'] * 100 / count_checks['total'], 2)
except Exception:
uptime = 0
try:
avg_res_time = round(sql.get_avg_resp_time(dashboard_id, check_id), 2)
except Exception:
@ -80,7 +72,62 @@ def smon_dashboard(dashboard_id, check_id):
)
@bp.route('/status-page')
@login_required
@get_user_params()
def status_page():
user_params = g.user_params
user_group = roxywi_common.get_user_group(id=1)
smon_list = sql.smon_list(user_group)
pages = sql.select_status_pages(user_group)
smon_status, stderr = smon_mod.return_smon_status()
user_subscription = roxywi_common.return_user_subscription()
return render_template(
'smon/manage_status_page.html', role=user_params['role'], user=user_params['user'], lang=user_params['lang'],
user_status=user_subscription['user_status'], user_plan=user_subscription['user_plan'], smon_error=stderr, pages=pages,
token=user_params['token'], user_services=user_params['user_services'], smon=smon_list, smon_status=smon_status
)
@bp.post('/status-page/add')
@login_required
def add_status_page():
name = common.checkAjaxInput(request.form.get('name'))
slug = common.checkAjaxInput(request.form.get('slug'))
desc = common.checkAjaxInput(request.form.get('desc'))
checks = json.loads(request.form.get('checks'))
if not len(checks['checks']):
return 'error: Please check Checks for Status page'
try:
return smon_mod.create_status_page(name, slug, desc, checks['checks'])
except Exception as e:
return f'{e}'
@bp.route('/status-page/delete/<int:page_id>')
@login_required
def delete_status_page(page_id):
try:
sql.delete_status_page(page_id)
except Exception as e:
return f'{e}'
else:
return 'ok'
@bp.route('/status/<slug>')
def show_smon_status_page(slug):
slug = common.checkAjaxInput(slug)
return smon_mod.show_status_page(slug)
@bp.route('/history')
@login_required
@get_user_params()
def smon_history():
roxywi_common.check_user_group_for_flask()
@ -99,6 +146,7 @@ def smon_history():
@bp.route('/history/host/<server_ip>')
@login_required
@get_user_params()
def smon_host_history(server_ip):
roxywi_common.check_user_group_for_flask()
@ -117,22 +165,25 @@ def smon_host_history(server_ip):
)
@bp.route('/history/metric/<int:dashboard_id>/<int:check_id>')
def smon_history_metric(dashboard_id, check_id):
return jsonify(smon_mod.history_metrics(dashboard_id, check_id))
@bp.route('/history/metric/<int:dashboard_id>')
@login_required
def smon_history_metric(dashboard_id):
return jsonify(smon_mod.history_metrics(dashboard_id))
@bp.route('/history/statuses/<int:dashboard_id>/<int:check_id>')
def smon_history_statuses(dashboard_id, check_id):
return smon_mod.history_statuses(dashboard_id, check_id)
@bp.route('/history/statuses/<int:dashboard_id>')
def smon_history_statuses(dashboard_id):
return smon_mod.history_statuses(dashboard_id)
@bp.route('/history/cur_status/<int:dashboard_id>/<int:check_id>')
@login_required
def smon_history_cur_status(dashboard_id, check_id):
return smon_mod.history_cur_status(dashboard_id, check_id)
@bp.route('/admin')
@login_required
@get_user_params()
def smon_admin():
user_group = roxywi_common.get_user_group(id=1)
@ -158,6 +209,7 @@ def smon_admin():
@bp.post('/add')
@login_required
def smon_add():
user_group = roxywi_common.get_user_group(id=1)
name = common.checkAjaxInput(request.form.get('newsmonname'))
@ -200,6 +252,7 @@ def smon_add():
@bp.post('/update/<smon_id>')
@login_required
def smon_update(smon_id):
roxywi_common.check_user_group_for_flask()
name = common.checkAjaxInput(request.form.get('updateSmonName'))
@ -232,6 +285,7 @@ def smon_update(smon_id):
@bp.route('/delete/<smon_id>')
@login_required
def smon_delete(smon_id):
user_group = roxywi_common.get_user_group(id=1)
@ -245,6 +299,7 @@ def smon_delete(smon_id):
@bp.post('/refresh')
@login_required
def smon_show():
sort = common.checkAjaxInput(request.form.get('sort'))
return smon_mod.show_smon(sort)

View File

@ -0,0 +1,15 @@
{% for page in pages %}
<div id="page_{{page}}" class="page_div">
<a href="/app/smon/status/{{page.slug}}" class="page_link" target="_blank" title="Open status page">
<i class="far fa-check-circle status-page-icon"></i>
<div>
<span class="page_name" id="page_name-{{page}}">{{page.name}}</span>
{% if page.desc %}
<span class="page_desc">({{page.desc|replace("'", "")}})</span>
{% endif %}
</div>
<div class="page_slug">/app/smon/status/{{page.slug}}</div>
</a>
<div class="delete" onclick="confirmDeleteStatusPage('{{page}}')"></div>
</div>
{% endfor %}

View File

@ -1,7 +1,7 @@
<html lang="{{lang|default('en')}}">
{% import 'languages/'+lang|default('en')+'.html' as lang %}
{% from 'languages/languages.html' import languages %}
{% from 'include/input_macros.html' import select, checkbox %}
<html lang="en">
<head>
<title>{% block title %}{% endblock %}</title>
<meta charset="UTF-8">
@ -20,7 +20,7 @@
data-stop="{{lang.words.stop|title()}}" data-reload="{{lang.words.reload|title()}}" data-user_groups="{{lang.phrases.user_groups}}" data-settings="{{lang.words.settings|title()}}"
data-for="{{lang.words.for}}" data-show="{{lang.words.show|title()}}" data-hide="{{lang.words.hide|title()}}" data-logs="{{lang.words.logs}}" data-name="{{lang.words.name}}"
data-value="{{lang.words.value}}" data-if-title="{{lang.words.if|title()}}" data-then="{{lang.words.then}}" data-autorefresh="{{lang.words.auto|title()}}-{{lang.words.refresh}}"
data-raw="{{lang.words.raw|title()}}" data-resp_time="{{lang.smon_page.desc.resp_time}}" />
data-raw="{{lang.words.raw|title()}}" data-resp_time="{{lang.smon_page.desc.resp_time}}" data-next="{{lang.words.next|title()}}" data-back="{{lang.words.back|title()}}" />
{% if title == 'Login page' %}
<meta name="viewport" content="width=device-width, user-scalable=1">
{% endif %}

View File

@ -97,6 +97,7 @@
"title": "Monitoring tools",
"smon": {
"dashboard": "SMON: Dashboard",
"status_page": "SMON: Status page",
"history": "SMON: History",
"admin": "SMON: Admin panel",
},
@ -319,6 +320,7 @@
"became_master": "Became Master",
"resource_record_type": "Resource Record Type",
"add_to_smon_desc": "Add the server for checking by SMON ping",
"create_page_status": "Create status page",
}
%}
{% set roles = {
@ -586,6 +588,7 @@
"edit": "edit",
"delete": "delete",
"add": "add",
"added": "added",
"save": "save",
"saved": "saved",
"saving": "saving",
@ -696,6 +699,7 @@
"virt": "virt",
"virtual": "virtual",
"check": "check",
"checks": "checks",
"checking": "checking",
"protected": "protected",
"slave_for": "Slave for",
@ -880,5 +884,6 @@
"map": "map",
"method": "method",
"tools": "tools",
"next": "next",
}
%}

View File

@ -97,6 +97,7 @@
"title": "Outils de monitoring",
"smon": {
"dashboard": "SMON: tableau de bord",
"status_page": "SMON: Page d'état",
"history": "SMON: Historique",
"admin": "SMON: Panneau administrateur",
},
@ -319,6 +320,7 @@
"became_master": "Devenu maître",
"resource_record_type": "Type d'enregistrement de ressource",
"add_to_smon_desc": "Ajouter le serveur pour vérification par SMON ping",
"create_page_status": "Créer une page de statut",
}
%}
{% set roles = {
@ -586,6 +588,7 @@
"edit": "éditer",
"delete": "supprimer",
"add": "ajouter",
"added": "ajoutée",
"save": "sauvegarder",
"saved": "sauvegardé",
"saving": "sauvegarde en cours",
@ -695,7 +698,8 @@
"enabled2": "activé",
"virt": "virt",
"virtual": "virtuel",
"check": "check",
"check": "contrôler",
"checks": "vérifications",
"checking": "vérifier",
"protected": "protégé",
"slave_for": "Esclave de",
@ -880,5 +884,6 @@
"map": "carte",
"method": "méthode",
"tools": "outils",
"next": "suivante",
}
%}

View File

@ -98,6 +98,7 @@
"smon": {
"dashboard": "SMON: Painel",
"history": "SMON: Histórico",
"status_page": "SMON: Página de status",
"admin": "SMON: Painel de administrador"
},
"checker_history": "Checker: Histórico",
@ -160,7 +161,7 @@
"checker_maxconn_threshold": "Valor limite para a notificação de maxconn, em %",
"checker_check_interval": "Intervalo de verificação para o Checker (em minutos)",
"smon_ssl_expire_warning_alert": "Aviso de alerta sobre a expiração do certificado SSL (em dias)",
"smon_ssl_expire_critical_alert": "Alerta critico a expiração do certificado SSL (em dias)"
"smon_ssl_expire_critical_alert": "Alerta critico a expiração do certificado SSL (em dias)",
"action_keep_history_range": "Período de retenção do histórico de ações (em dias)",
},
"main": {
@ -319,6 +320,7 @@
"became_master": "Tornou-se mestre",
"resource_record_type": "Tipo de registro de recurso",
"add_to_smon_desc": "Adicione o servidor para verificação por ping SMON",
"create_page_status": "Criar página de status",
}
%}
{% set roles = {
@ -586,6 +588,7 @@
"edit": "editar",
"delete": "apagar",
"add": "adicionar",
"added": "adicionada",
"save": "salvar",
"saved": "salvo",
"saving": "salvando",
@ -696,6 +699,7 @@
"virt": "virt",
"virtual": "virtual",
"check": "verificar",
"checks": "verificações",
"checking": "verificando",
"protected": "protegido",
"slave_for": "Escravo para",
@ -880,5 +884,6 @@
"map": "mapa",
"method": "método",
"tools": "ferramentas",
"next": "próxima",
}
%}

View File

@ -97,6 +97,7 @@
"title": "Инструменты для мониторинга",
"smon": {
"dashboard": "SMON: Дашборд",
"status_page": "SMON: Страница статуса",
"history": "SMON: История",
"admin": "SMON: Админка",
},
@ -157,7 +158,7 @@
"portscanner_keep_history_range": "Время хранения истории Port scanner",
"smon_keep_history_range": "Время хранения истории SMON",
"checker_keep_history_range": "Время хранения истории Checker",
"checker_maxconn_threshold": "Порог срабатывания уведомления по maxconn, в %",,
"checker_maxconn_threshold": "Порог срабатывания уведомления по maxconn, в %",
"checker_check_interval": "Интервал проверки для Checker (в минутах)",
"smon_ssl_expire_warning_alert": "Предупреждение о истечении SSL-сертификата (в днях)",
"smon_ssl_expire_critical_alert": "Критическое предупреждение о истечении SSL-сертификата (в днях)",
@ -319,6 +320,7 @@
"became_master": "Стал мастером",
"resource_record_type": "Тип записи ресурса",
"add_to_smon_desc": "Добавить сервер для проверки с помощью SMON ping",
"create_page_status": "Создать страницу статуса",
}
%}
{% set roles = {
@ -586,6 +588,7 @@
"edit": "редактировать",
"delete": "удалить",
"add": "добавить",
"added": "добавленные",
"save": "сохранить",
"saved": "сохраненные",
"saving": "сохранения",
@ -696,6 +699,7 @@
"virt": "вирт",
"virtual": "виртуальный",
"check": "проверить",
"checks": "проверки",
"checking": "проверка",
"protected": "защищенный",
"slave_for": "Подчинен",
@ -880,5 +884,6 @@
"map": "карта",
"method": "метод",
"tools": "инструменты",
"next": "дальше",
}
%}

View File

@ -18,6 +18,7 @@
border: 1px solid #ccc;
}
</style>
<script src="/inc/nettools.js"></script>
<form name="nettools_icmp_form" id="nettools_icmp_form" method="post" action="/app/nettols/icmp">
<table class="overview">
<caption><h3>ICMP</h3></caption>
@ -117,110 +118,25 @@
</tr>
</table>
</form>
<form name="nettools_portscanner_form" id="nettools_portscanner_form" method="post" action="/app/nettols/portscan">
<table class="overview">
<caption><h3>Port scanner</h3></caption>
<tr class="overviewHead">
<th class="padding10 first-collumn">{{lang.words.server|title()}}</th>
<th></th>
</tr>
<tr>
<td class="padding10 first-collumn">
{{ input('nettools_portscanner_server', title='Enter a server for port scanning') }}
</td>
<td class="padding10" style="width: 0">
<button type="submit" title="{{lang.words.run|title()}} port scanning" id="nettools_portscan" name="nettools_portscan" value="nettools_portscan">{{lang.words.run|title()}}</button>
</td>
</tr>
</table>
</form>
<div id="ajax-nettools" style="padding: 20px;"></div>
<script>
$("#nettools_nslookup_record_type" ).selectmenu({
width: 175
});
$( "#nettools_telnet_form" ).on("click", ":submit", function(e){
$('#ajax-nettools').html('');
var frm = $('#nettools_telnet_form');
if($('#nettools_telnet_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if($('#nettools_telnet_server_to').val() == '') {
toastr.warning('Choose a server To');
return false;
}
if($('#nettools_telnet_port_to').val() == '') {
toastr.warning('Enter a port To');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function( data ) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
$('#ajax-nettools').html('<div class="ping_pre">'+data+'</div>');
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
if (data.indexOf('') != '-1') {
$('#ajax-nettools').html('<div class="ping_pre"><b>Connection has been successful</b></div>');
} else {
$('#ajax-nettools').html('<div class="ping_pre"><b>Connection has been successful</b>:<br /><br />'+data+'</div>');
}
}
}
});
event.preventDefault();
});
$( "#nettools_nslookup_form" ).on("click", ":submit", function(e){
$('#ajax-nettools').html('');
var frm = $('#nettools_nslookup_form');
if($('#nettools_nslookup_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if($('#nettools_nslookup_name').val() == '') {
toastr.warning('Enter a DNS name');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function( data ) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
toastr.clear();
toastr.error(data);
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
$('#ajax-nettools').html('<div class="ping_pre">'+data+'</div>');
}
}
});
event.preventDefault();
});
$( "#nettools_icmp_form" ).on("click", ":submit", function(e){
$('#ajax-nettools').html('');
var frm = $('#nettools_icmp_form');
if($('#nettools_icmp_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if($('#nettools_icmp_server_to').val() == '') {
toastr.warning('Enter a server To');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize() + "&nettools_action=" + $(this).val(),
type: frm.attr('method'),
success: function( data ) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
toastr.clear();
toastr.error(data);
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
$('#ajax-nettools').html('<div class="ping_pre">'+data+'</div>');
}
}
});
event.preventDefault();
});
</script>
<div id="show_scans_ports" style="display: none; padding: 0;">
<div id="show_scans_ports_body"></div>
</div>
{% endblock %}

View File

@ -262,7 +262,7 @@
{% endif %}
</div>
<div class="server-desc">
{% if s.3 is none %}
{% if s.3 == '' %}
{{lang.words.no_desc|title()}}
{% else %}
{{s.3}}

View File

@ -0,0 +1,101 @@
{% extends "base.html" %}
{% block title %}{{ lang.menu_links.monitoring.smon.status_page }}{% endblock %}
{% block h2 %}{{ lang.menu_links.monitoring.smon.status_page }}{% endblock %}
{% block content %}
{% from 'include/input_macros.html' import input, select %}
<script src="/inc/smon.js"></script>
<link href="/inc/css/servers.css" rel="stylesheet"/>
<link href="/inc/css/smon.css" rel="stylesheet"/>
{% if user_status == 0 or user_plan != 'support' %}
{% include 'include/no_sub.html' %}
{% elif smon_error != '' %}
<div style="text-align: center;">
<br />
<h3>{{lang.smon_page.desc.not_installed}}</h3>.
<img src="{{ url_for('static', filename='images/no_servers.png')}}" alt="There is no server">
<h4>{{lang.words.read|title()}} <a href="https://roxy-wi.org/services/smon" title="Simple monitoring network ports with alerting via Telegram and WEB panel" target="_blank">{{lang.words.here}}</a>
{{lang.phrases.how_to_install}} SMON {{lang.words.service}}.</h4>
</div>
{% elif smon_status.0 == 'failed' or smon_status.0 == 'inactive' %}
<div style="text-align: center;">
<br />
<h3>{{lang.smon_page.desc.smon_is_not_run}}</h3>
<img src="{{ url_for('static', filename='images/no_servers.png')}}" alt="There is no server">
<h4>{{lang.smon_page.desc.run_smon}} <a href="/app/users/services" title="Roxy-WI services" target="_blank">{{lang.words.here}}</a> {{lang.smon_page.desc.before_use}}</h4>
</div>
{% elif pages|length == 0 %}
<div style="text-align: center;">
<br />
<h3>{{lang.phrases.no_events_added}}</h3>
<img src="{{ url_for('static', filename='images/no_servers.png')}}" alt="There is no server">
<h4>Click <a href="/app/smon/admin" title="Roxy-WI SMON" target="_blank">{{lang.words.here}}</a> {{lang.smon_page.desc.see_check}}</h4>
<br />
</div>
{% else %}
<div class="add-button add-button-status-page" title="SMOM: {{lang.phrases.create_page_status}} - Roxy-WI" onclick="createStatusPageStep1();">+ {{lang.phrases.create_page_status}}</div>
<div id="pages">
{% include 'ajax/smon/status_pages.html' %}
</div>
<div id="create-status-page-step-1" style="display: none;">
<table class="overview" id="create-status-page-step-1-overview" title="{{lang.words.create|title()}} {{lang.words.w_a}} {{lang.words.new2}} {{lang.words.status}} {{lang.words.page}}">
{% include 'include/tr_validate_tips.html' %}
<tr>
<td class="padding20">
{{lang.words.name|title()}}
<span class="need-field">*</span>
</td>
<td>
{{ input('new-status-page-name', autofocus='autofocus') }}
</td>
</tr>
<tr>
<td class="padding20">
Slug
<span class="need-field">*</span>
</td>
<td>
<span style="margin-top: 10px;display: inline-block;margin-right: -5px;">/app/smon/status/</span>{{ input('new-status-page-slug') }}
<ul class="tooltip tooltipTop">
<li>Accept characters: a-z 0-9 -</li>
<li>No consecutive dashes --</li>
</ul>
</td>
</tr>
</table>
</div>
<div id="create-status-page-step-2" style="display: none;">
<table class="overview" id="create-status-page-step-2-overview" title="{{lang.words.create|title()}} {{lang.words.w_a}} {{lang.words.new2}} {{lang.words.status}} {{lang.words.page}}">
{% include 'include/tr_validate_tips.html' %}
<tr>
<td class="padding20" style="width: 50%">
{{lang.words.desc|title()}}
</td>
<td>
{{ input('new-status-page-desc', autofocus='autofocus') }}
</td>
</tr>
<tr>
<td class="padding20">
{{lang.words.all|title()}} {{lang.words.checks}}
</td>
<td>{{lang.words.added|title()}} {{lang.words.checks}}</td>
</tr>
</table>
<div class="checks">
<div class="enabled-check" id="enabled-check"></div>
<div id="all-checks">
{% for s in smon %}
<div class="{{ loop.cycle('odd', 'even') }} all-checks" id="add_check-{{ s.id }}" data-service_name="{{ s.name }} - {{s.group}}">
<div class="check-name" title="{{s.desc}}">{{ s.name }} - {{s.group}}</div>
<div class="add_user_group check-button" title="{{lang.words.add|title()}} {{lang.words.service}}" onclick="addCheckToStatus('{{ s.id }}')">+</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div id="dialog-confirm" style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>{{lang.phrases.are_you_sure}}</p>
</div>
{% endif %}
{% endblock %}

View File

@ -0,0 +1,57 @@
<html lang="{{lang|default('en')}}">
{% import 'languages/'+lang|default('en')+'.html' as lang %}
{% for p in page %}
<head>
<title>{{p.name}}</title>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<link rel="icon" type="image/png" href="{{ url_for('static', filename='images/favicon/favicon.ico') }}" />
<link rel="apple-touch-icon" sizes="57x57" href="{{ url_for('static', filename='images/favicon/apple-icon-57x57.png') }}">
<link rel="apple-touch-icon" sizes="60x60" href="{{ url_for('static', filename='images/favicon/apple-icon-60x60.png') }}">
<link rel="apple-touch-icon" sizes="72x72" href="{{ url_for('static', filename='images/favicon/apple-icon-72x72.png') }}">
<link rel="apple-touch-icon" sizes="76x76" href="{{ url_for('static', filename='images/favicon/apple-icon-76x76.png') }}">
<link rel="apple-touch-icon" sizes="114x114" href="{{ url_for('static', filename='images/favicon/apple-icon-114x114.png') }}">
<link rel="apple-touch-icon" sizes="120x120" href="{{ url_for('static', filename='images/favicon/apple-icon-120x120.png') }}">
<link rel="apple-touch-icon" sizes="144x144" href="{{ url_for('static', filename='images/favicon/apple-icon-144x144.png') }}">
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='images/favicon/apple-icon-152x152.png') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='images/favicon/apple-icon-180x180.png') }}">
<link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='images/favicon/android-icon-192x192.png') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='images/favicon/favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="96x96" href="{{ url_for('static', filename='images/favicon/favicon-96x96.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='images/favicon/favicon-16x16.png') }}">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="{{ url_for('static', filename='images/favicon/ms-icon-144x144.png') }}">
<meta name="theme-color" content="#ffffff">
<link href="/inc/css/jquery-ui.min.css" rel="stylesheet">
<link href="/inc/css/jquery-ui.structure.min.css" rel="stylesheet">
<link href="/inc/css/style-6.3.9.css" rel="stylesheet">
<link href="/inc/css/smon.css" rel="stylesheet">
<script src="/inc/jquery-3.6.0.min.js"></script>
<script src="/inc/jquery-ui.min.js"></script>
<script src="/inc/smon.js"></script>
<link href="/inc/css/toastr-6.3.9.css" rel="stylesheet"/>
<script src="/inc/toastr.js"></script>
</head>
<body>
<h2>Status page - {{p.name}}</h2>
<h3>{{p.desc|replace("'", "")}}</h3>
{% for check, value in checks_status.items() %}
{% if value.uptime|int() < 90 %}
{% set add_class = 'serverDown' %}
{% else %}
{% set add_class = 'serverUP' %}
{% endif %}
<div class="check_div">
<div>
<span class="{{add_class}} check_uptime">{{value.uptime}}%</span>
<span class="check_name">{{value.name}}</span>
</div>
<div class="history_statuses" id="history-{{check}}"></div>
</div>
<script>show_smon_history_statuses('{{check}}', '#history-{{check}}');</script>
{% endfor %}
</body>
</html>
{% endfor %}

View File

@ -70,3 +70,114 @@ h4 {
font-size: 13px;
color: #aaa;
}
.checks {
height: 400px;
overflow-y: overlay;
}
.all-checks, .enabled-check {
height: 40px;
width: 300px;
}
.enabled-check {
float: right;
}
.add_user_group{
height: 14px;
}
.check-name {
margin-left: 15px;
margin-top: 10px;
width: 245px;
float: left;
}
.check-button {
float: left;
margin-top: 3px;
}
.add-button-status-page {
font-size: 15px;
float: unset;
margin: var(--indent);
width: fit-content;
}
.page_div {
margin: var(--indent);
border-top: 1px solid #ddd;
transition: all ease-in-out .15s;
padding: 5px 10px 10px;
margin-bottom: 0;
margin-top: 0;
}
.page_link {
color: black;
text-decoration: none !important;
}
.page_div:hover {
background-color: var(--light-blue-color);
}
.page_name {
font-size: 20px;
font-weight: 700;
}
.page_desc {
font-size: 15px;
}
.page_slug {
font-size: 10px;
}
.status-page-icon {
float: left;
margin: 10px;
margin-top: 0px;
font-size: 50px;
margin-right: 25px;
margin-left: 0;
color: var(--green-color);
}
.delete {
float: left;
margin-left: 99%;
margin-top: -45px;
font-size: 17px;
cursor: pointer;
}
.check_div {
width: 50%;
padding: 20px 30px 20px 30px;
margin-left: 20%;
margin-top: 10px;
margin-bottom: 10px;
}
.check_div:hover {
background-color: var(--light-blue-color);
}
.check_uptime {
border-radius: 10px;
padding-left: 10px;
padding-right: 10px;
}
.check_name {
margin-left: 10px;
font-size: 15px;
font-weight: 550;
}
.history_statuses {
float: right;
margin-top: -20px;
}
.smon_server_statuses {
width: 1px;
height: 10px;
margin: 1px;
}
.validateTips {
width: 575px;
}
.tooltipTop {
padding-top: 10px;
list-style: disc;
margin-left: 20px;
}
.tooltipTop {
margin-bottom: 0;
}

View File

@ -583,9 +583,9 @@ function updatingCpuRamCharts() {
removeData();
}
}
function getSmonHistoryCheckData(server, check_id) {
function getSmonHistoryCheckData(server) {
$.ajax({
url: "/app/smon/history/metric/" + server + "/" + check_id,
url: "/app/smon/history/metric/" + server,
// data: {
// time_range: $( "#time-range option:selected" ).val(),
// },

140
inc/nettools.js Normal file
View File

@ -0,0 +1,140 @@
$( function() {
$("#nettools_nslookup_record_type").selectmenu({
width: 175
});
$("#nettools_telnet_form").on("click", ":submit", function (e) {
$('#ajax-nettools').html('');
var frm = $('#nettools_telnet_form');
if ($('#nettools_telnet_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if ($('#nettools_telnet_server_to').val() == '') {
toastr.warning('Choose a server To');
return false;
}
if ($('#nettools_telnet_port_to').val() == '') {
toastr.warning('Enter a port To');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function (data) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
$('#ajax-nettools').html('<div class="ping_pre">' + data + '</div>');
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
if (data.indexOf('') != '-1') {
$('#ajax-nettools').html('<div class="ping_pre"><b>Connection has been successful</b></div>');
} else {
$('#ajax-nettools').html('<div class="ping_pre"><b>Connection has been successful</b>:<br /><br />' + data + '</div>');
}
}
}
});
event.preventDefault();
});
$("#nettools_nslookup_form").on("click", ":submit", function (e) {
$('#ajax-nettools').html('');
var frm = $('#nettools_nslookup_form');
if ($('#nettools_nslookup_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if ($('#nettools_nslookup_name').val() == '') {
toastr.warning('Enter a DNS name');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function (data) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
toastr.clear();
toastr.error(data);
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
$('#ajax-nettools').html('<div class="ping_pre">' + data + '</div>');
}
}
});
event.preventDefault();
});
$("#nettools_icmp_form").on("click", ":submit", function (e) {
$('#ajax-nettools').html('');
var frm = $('#nettools_icmp_form');
if ($('#nettools_icmp_server_from option:selected').val() == '------') {
toastr.warning('Choose a server From');
return false;
}
if ($('#nettools_icmp_server_to').val() == '') {
toastr.warning('Enter a server To');
return false;
}
$.ajax({
url: frm.attr('action'),
data: frm.serialize() + "&nettools_action=" + $(this).val(),
type: frm.attr('method'),
success: function (data) {
data = data.replace('\n', "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error(s)') != '-1') {
toastr.clear();
toastr.error(data);
} else if (data.indexOf('warning: ') != '-1') {
toastr.clear();
toastr.warning(data)
} else {
toastr.clear();
$('#ajax-nettools').html('<div class="ping_pre">' + data + '</div>');
}
}
});
event.preventDefault();
});
$("#nettools_portscanner_form").on("click", ":submit", function (e) {
$('#ajax-nettools').html('');
if ($('#nettools_portscanner_server').val() == '') {
toastr.warning('Enter an address');
return false;
}
$.ajax({
url: "/app/portscanner/scan/" + $('#nettools_portscanner_server').val(),
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('danger') != '-1' || data.indexOf('unique') != '-1' || data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
toastr.clear();
$("#show_scans_ports_body").html(data);
var close_word = $('#translate').attr('data-close');
$("#show_scans_ports").dialog({
resizable: false,
height: "auto",
width: 360,
modal: true,
title: "{{lang.words.opened|title()}} {{lang.words.ports}}",
buttons: [{
text: close_word,
click: function () {
$(this).dialog("close");
$("#show_scans_ports_body").html('');
}
}]
});
}
}
});
event.preventDefault();
});
});

View File

@ -100,6 +100,8 @@ $( function() {
show_current_page($(this))
} else if (full_uri == 'smon/history' && full_uri1 == 'smon/history') {
show_current_page($(this))
} else if (full_uri == 'smon/status-page' && full_uri1 == 'smon/status-page') {
show_current_page($(this))
} else if (full_uri == 'checker/settings' && full_uri1 == 'checker/settings') {
show_current_page($(this))
} else if (full_uri == 'checker/history' && full_uri1 == 'checker/history') {

View File

@ -359,7 +359,6 @@ function check_and_clear_check_type(check_type) {
$("#check_type").val('ping');
$('#check_type').selectmenu("refresh");
clear_check_vals();
}
}
function clear_check_vals() {
@ -369,25 +368,8 @@ function clear_check_vals() {
$('#new-smon-port').val('');
$('#new-smon-packet_size').val('');
}
function show_statuses(dashboard_id, check_id) {
$.ajax({
url: "/app/smon/history/statuses/" + dashboard_id + "/" + check_id,
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else {
toastr.clear();
$("#smon_history_statuses").html(data);
$( "[title]" ).tooltip({
"content": function () {
return $(this).attr("data-help");
},
show: {"delay": 1000}
});
}
}
});
function show_statuses(dashboard_id, check_id, id_for_history_replace) {
show_smon_history_statuses(dashboard_id, id_for_history_replace);
$.ajax({
url: "/app/smon/history/cur_status/" + dashboard_id + "/" + check_id,
success: function (data) {
@ -401,3 +383,226 @@ function show_statuses(dashboard_id, check_id) {
}
});
}
function show_smon_history_statuses(dashboard_id, id_for_history_replace) {
$.ajax({
url: "/app/smon/history/statuses/" + dashboard_id,
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else {
toastr.clear();
$(id_for_history_replace).html(data);
$("[title]").tooltip({
"content": function () {
return $(this).attr("data-help");
},
show: {"delay": 1000}
});
}
}
});
}
function createStatusPageStep1() {
var add_word = $('#translate').attr('data-next');
var cancel_word = $('#translate').attr('data-cancel');
var next_word = $('#translate').attr('data-next');
var smon_add_tabel_title = $( "#create-status-page-step-1-overview" ).attr('title');
var regx = /^[a-z0-9_-]+$/;
var addSmonStatus = $( "#create-status-page-step-1" ).dialog({
autoOpen: false,
resizable: false,
height: "auto",
width: 630,
modal: true,
title: smon_add_tabel_title,
show: {
effect: "fade",
duration: 200
},
hide: {
effect: "fade",
duration: 200
},
buttons: [{
text: next_word,
click: function () {
if ($('#new-status-page-name').val() == '') {
toastr.error('error: Fill in the Name field');
return false;
}
if (!regx.test($('#new-status-page-slug').val())) {
toastr.error('error: Incorect Slug');
return false;
}
if ($('#new-status-page-slug').val().indexOf('--') != '-1') {
toastr.error('error: "--" are prohibeted in Slug');
return false;
}
if ($('#new-status-page-slug').val() == '') {
toastr.error('error: Fill in the Slug field');
return false;
}
createStatusPageStep2();
$(this).dialog("close");
toastr.clear();
}
}, {
text: cancel_word,
click: function () {
$(this).dialog("close");
clearTips();
}
}]
});
addSmonStatus.dialog('open');
}
function createStatusPageStep2() {
var add_word = $('#translate').attr('data-add');
var cancel_word = $('#translate').attr('data-cancel');
var back_word = $('#translate').attr('data-back');
var smon_add_tabel_title = $("#create-status-page-step-2-overview").attr('title');
var addSmonStatus = $("#create-status-page-step-2").dialog({
autoOpen: false,
resizable: false,
height: "auto",
width: 630,
modal: true,
title: smon_add_tabel_title,
show: {
effect: "fade",
duration: 200
},
hide: {
effect: "fade",
duration: 200
},
buttons: [{
text: add_word,
click: function () {
createStatusPage($(this));
}
}, {
text: back_word,
click: function () {
$(this).dialog("close");
createStatusPageStep1();
}
}, {
text: cancel_word,
click: function () {
$(this).dialog("close");
clearTips();
}
}]
});
addSmonStatus.dialog('open');
}
function createStatusPage(dialog_id) {
let name_id = $('#new-status-page-name');
let slug_id = $('#new-status-page-slug');
let desc_id = $('#new-status-page-desc');
let checks = [];
let check_id = '';
$("#enabled-check > div").each((index, elem) => {
check_id = elem.id.split('-')[1]
checks.push(check_id);
});
$.ajax({
url: '/app/smon/status-page/add',
type: 'POST',
data: {
name: name_id.val(),
slug: slug_id.val(),
desc: desc_id.val(),
checks: JSON.stringify({'checks': checks})
},
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else {
toastr.clear();
$("#smon_history_statuses").html(data);
for (let i = 0; i < checks.length; i++) {
removeCheckFromStatus(checks[i]);
console.log(checks[i])
}
name_id.val('');
slug_id.val('');
dialog_id.dialog("close");
$("#pages").append(data);
setTimeout(function () {
$("#user-" + id).removeClass("update");
}, 2500);
$.getScript("/inc/fontawesome.min.js");
}
}
});
}
function addCheckToStatus(service_id) {
var service_name = $('#add_check-' + service_id).attr('data-service_name');
var delete_word = $('#translate').attr('data-delete');
var service_word = $('#translate').attr('data-service');
var length_tr = $('#all-checks').length;
var tr_class = 'odd';
if (length_tr % 2 != 0) {
tr_class = 'even';
}
var html_tag = '<div class="' + tr_class + '" id="remove_check-' + service_id + '" data-service_name="' + service_name + '">' +
'<div class="check-name">' + service_name + '</div>' +
'<div class="add_user_group check-button" onclick="removeCheckFromStatus(' + service_id + ')" title="' + delete_word + ' ' + service_word + '">-</div></div>';
$('#add_check-' + service_id).remove();
$("#enabled-check").append(html_tag);
}
function removeCheckFromStatus(service_id) {
var service_name = $('#remove_check-' + service_id).attr('data-service_name');
var add_word = $('#translate').attr('data-add');
var service_word = $('#translate').attr('data-service');
var length_tr = $('#all_services tbody tr').length;
var tr_class = 'odd';
if (length_tr % 2 != 0) {
tr_class = 'even';
}
var html_tag = '<div class="' + tr_class + ' all-checks" id="add_check-' + service_id + '" data-service_name="' + service_name + '">' +
'<div class="check-name">' + service_name + '</div>' +
'<div class="add_user_group check-button" onclick="addCheckToStatus(' + service_id + ')" title="' + add_word + ' ' + service_word + '">+</div></div>';
$('#remove_check-' + service_id).remove();
$("#all-checks").append(html_tag);
}
function confirmDeleteStatusPage(id) {
var delete_word = $('#translate').attr('data-delete');
var cancel_word = $('#translate').attr('data-cancel');
$("#dialog-confirm").dialog({
resizable: false,
height: "auto",
width: 400,
modal: true,
title: delete_word + " " + $('#page_name-' + id).text() + "?",
buttons: [{
text: delete_word,
click: function () {
$(this).dialog("close");
deleteStatusPage(id);
}
}, {
text: cancel_word,
click: function () {
$(this).dialog("close");
}
}]
});
}
function deleteStatusPage(page_id) {
$.ajax({
url: '/app/smon/status-page/delete/' + page_id,
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else {
$('#page_' + page_id).remove();
}
}
});
}