Додан моніторінг застосунку
Додани веб компоненти карточок територій та повідомлень
@@ -31,6 +31,9 @@ DOMAIN=sheep-service.com
|
|||||||
HTTP_PORT=4000
|
HTTP_PORT=4000
|
||||||
HTTPS_PORT=4001
|
HTTPS_PORT=4001
|
||||||
|
|
||||||
|
ADMIN_USER=<тут_твій_нікнейм>
|
||||||
|
ADMIN_TOKEN=<тут_твій_токен>
|
||||||
|
|
||||||
DB_PATH=/home/username/webapps/sheep-service.com/
|
DB_PATH=/home/username/webapps/sheep-service.com/
|
||||||
CARDS_PATH=/home/username/webapps/sheep-service.com/cards
|
CARDS_PATH=/home/username/webapps/sheep-service.com/cards
|
||||||
MAP_PATH=/home/username/webapps/sheep-service.com/map
|
MAP_PATH=/home/username/webapps/sheep-service.com/map
|
||||||
|
|||||||
@@ -44,6 +44,24 @@ class SheepsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getListStand(req, res) {
|
||||||
|
if (req.possibilities.can_view_stand) {
|
||||||
|
const result = await SheepsService.getListStand(req.mode);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return res.status(200).send(result);
|
||||||
|
} else {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.send({ message: 'User not found.' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.send({ message: 'The sheep does not have enough rights.' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async createSheep(req, res) {
|
async createSheep(req, res) {
|
||||||
const data = req.body;
|
const data = req.body;
|
||||||
|
|
||||||
|
|||||||
22
api/middleware/metrics.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
module.exports = (req, res, next) => {
|
||||||
|
const start = performance.now();
|
||||||
|
|
||||||
|
res.on("finish", () => {
|
||||||
|
const duration = performance.now() - start;
|
||||||
|
|
||||||
|
fetch("http://metrics:4005/push", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
type: "rest",
|
||||||
|
path: req.originalUrl,
|
||||||
|
method: req.method,
|
||||||
|
status: res.statusCode,
|
||||||
|
time: duration,
|
||||||
|
timestamp: Date.now()
|
||||||
|
})
|
||||||
|
}).catch(err => console.error(err));
|
||||||
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
const metrics = require('../middleware/metrics');
|
||||||
|
|
||||||
const authRoutes = require('./auth.routes');
|
const authRoutes = require('./auth.routes');
|
||||||
const sheepsRoutes = require('./sheeps.routes');
|
const sheepsRoutes = require('./sheeps.routes');
|
||||||
const constructorRoutes = require('./constructor.routes');
|
const constructorRoutes = require('./constructor.routes');
|
||||||
@@ -18,6 +20,9 @@ const pushRoutes = require('./push.routes');
|
|||||||
const generatorCardsRoutes = require('./generator.cards.routes');
|
const generatorCardsRoutes = require('./generator.cards.routes');
|
||||||
const generatorReportTerritoriesRoutes = require('./generator.report.territories.routes');
|
const generatorReportTerritoriesRoutes = require('./generator.report.territories.routes');
|
||||||
|
|
||||||
|
|
||||||
|
router.use(metrics);
|
||||||
|
|
||||||
router.use('/auth', authRoutes);
|
router.use('/auth', authRoutes);
|
||||||
router.use('/sheeps?', sheepsRoutes);
|
router.use('/sheeps?', sheepsRoutes);
|
||||||
router.use('/constructor', constructorRoutes);
|
router.use('/constructor', constructorRoutes);
|
||||||
|
|||||||
@@ -15,4 +15,8 @@ router
|
|||||||
.route('/list')
|
.route('/list')
|
||||||
.get(authenticate, SheepsController.getList);
|
.get(authenticate, SheepsController.getList);
|
||||||
|
|
||||||
|
router
|
||||||
|
.route('/list/stand')
|
||||||
|
.get(authenticate, SheepsController.getListStand);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
@@ -75,6 +75,7 @@ class SheepService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getList(mode) {
|
getList(mode) {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
const sql = `
|
const sql = `
|
||||||
@@ -147,6 +148,82 @@ class SheepService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getListStand(mode) {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
sheeps.*,
|
||||||
|
possibilities.can_add_sheeps,
|
||||||
|
possibilities.can_view_sheeps,
|
||||||
|
possibilities.can_add_territory,
|
||||||
|
possibilities.can_view_territory,
|
||||||
|
possibilities.can_manager_territory,
|
||||||
|
possibilities.can_add_stand,
|
||||||
|
possibilities.can_view_stand,
|
||||||
|
possibilities.can_manager_stand,
|
||||||
|
possibilities.can_add_schedule,
|
||||||
|
possibilities.can_view_schedule
|
||||||
|
FROM
|
||||||
|
sheeps
|
||||||
|
LEFT JOIN
|
||||||
|
possibilities ON possibilities.sheep_id = sheeps.id
|
||||||
|
WHERE
|
||||||
|
possibilities.can_view_stand = '1'
|
||||||
|
ORDER BY
|
||||||
|
sheeps.group_id;
|
||||||
|
`;
|
||||||
|
|
||||||
|
db.all(sql, (err, rows) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
return res(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
"can_add_sheeps",
|
||||||
|
"can_view_sheeps",
|
||||||
|
"can_add_territory",
|
||||||
|
"can_view_territory",
|
||||||
|
"can_manager_territory",
|
||||||
|
"can_add_stand",
|
||||||
|
"can_view_stand",
|
||||||
|
"can_manager_stand",
|
||||||
|
"can_add_schedule",
|
||||||
|
"can_view_schedule"
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = rows.map(sheep => {
|
||||||
|
const data = {
|
||||||
|
id: sheep.id,
|
||||||
|
group_id: sheep.group_id,
|
||||||
|
name: sheep.name,
|
||||||
|
icon: sheep.icon,
|
||||||
|
uuid: (mode && mode == 2) ? sheep.uuid : null,
|
||||||
|
uuid_manager: (mode && mode == 2) ? sheep.uuid_manager : null,
|
||||||
|
mode: mode ? Number(sheep.mode) : 0,
|
||||||
|
mode_title: sheep.mode_title,
|
||||||
|
possibilities: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
fields.forEach(f => {
|
||||||
|
data.possibilities[f] = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mode && (mode == 1 || mode == 2)) {
|
||||||
|
fields.forEach(f => {
|
||||||
|
data.possibilities[f] = !!sheep[f];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
|
res(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
createSheep(data) {
|
createSheep(data) {
|
||||||
const stmt1 = db.prepare('INSERT INTO sheeps(name, group_id, uuid) VALUES (?, ?, ?)');
|
const stmt1 = db.prepare('INSERT INTO sheeps(name, group_id, uuid) VALUES (?, ?, ?)');
|
||||||
const stmt2 = db.prepare('INSERT INTO possibilities(can_view_territory, sheep_id) VALUES (?, ?)');
|
const stmt2 = db.prepare('INSERT INTO possibilities(can_view_territory, sheep_id) VALUES (?, ?)');
|
||||||
@@ -175,6 +252,7 @@ class SheepService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSheep(data) {
|
updateSheep(data) {
|
||||||
const stmt1 = db.prepare(`
|
const stmt1 = db.prepare(`
|
||||||
UPDATE
|
UPDATE
|
||||||
@@ -241,6 +319,7 @@ class SheepService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteSheep(data) {
|
deleteSheep(data) {
|
||||||
const stmtSelect = db.prepare('SELECT id FROM sheeps WHERE uuid = ?');
|
const stmtSelect = db.prepare('SELECT id FROM sheeps WHERE uuid = ?');
|
||||||
const stmtDeletePoss = db.prepare('DELETE FROM possibilities WHERE sheep_id = ?');
|
const stmtDeletePoss = db.prepare('DELETE FROM possibilities WHERE sheep_id = ?');
|
||||||
|
|||||||
163
dash.json
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "prometheus"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"target": {
|
||||||
|
"limit": 100,
|
||||||
|
"matchAny": false,
|
||||||
|
"tags": [],
|
||||||
|
"type": "dashboard"
|
||||||
|
},
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"graphTooltip": 1,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "palette-classic" },
|
||||||
|
"custom": {
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillBorderColor": "rgba(255, 255, 255, 1)",
|
||||||
|
"gradientMode": "none",
|
||||||
|
"lineStyle": "solid",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"scaleDistribution": { "type": "linear" },
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": { "group": "A", "mode": "none" },
|
||||||
|
"thresholdsStyle": { "mode": "off" }
|
||||||
|
},
|
||||||
|
"unit": "ms"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 0 },
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": { "calcs": ["mean", "max"], "displayMode": "list", "placement": "bottom" },
|
||||||
|
"tooltip": { "mode": "single", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "frontend_load_time", "legendFormat": "Завантаження: {{instance}}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Час завантаження Frontend (ms)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": { "mode": "palette-classic" },
|
||||||
|
"unit": "short"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 8, "y": 0 },
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["last"],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom"
|
||||||
|
},
|
||||||
|
"tooltip": { "mode": "single", "sort": "none" }
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "users_online", "legendFormat": "Онлайн користувачі", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Онлайн користувачі (Gauge)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 16, "y": 0 },
|
||||||
|
"id": 10,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rest_request_duration_ms",
|
||||||
|
"legendFormat": "{{path}} ({{status}})",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "REST Запити (Duration)",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 0, "y": 8 },
|
||||||
|
"id": 6,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(ws_in_bytes_total[5m])",
|
||||||
|
"legendFormat": "Вхідний WS-трафік (байт/сек)",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "rate(ws_out_bytes_total[5m])",
|
||||||
|
"legendFormat": "Вихідний WS-трафік (байт/сек)",
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "WS трафік (Rate)"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 8, "y": 8 },
|
||||||
|
"id": 16,
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "frontend_resource_count", "legendFormat": "Кількість ресурсів", "refId": "A" }
|
||||||
|
],
|
||||||
|
"title": "Кількість завантажених ресурсів",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"datasource": { "type": "datasource", "uid": "prometheus" },
|
||||||
|
"gridPos": { "h": 8, "w": 8, "x": 16, "y": 8 },
|
||||||
|
"id": 14,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "frontend_memory_used",
|
||||||
|
"legendFormat": "Використано JS Heap (MB)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Використання JS Heap (MB)",
|
||||||
|
"type": "timeseries"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"refresh": "5s",
|
||||||
|
"schemaVersion": 38,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": ["Sheep Service", "pushgateway"],
|
||||||
|
|
||||||
|
"time": { "from": "now-30m", "to": "now" },
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "Sheep Service Metrics",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
BIN
data/cards/cache/house/T81.png
vendored
Normal file
|
After Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 38 KiB |
BIN
data/cards/homestead/H53.webp
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
data/cards/homestead/H54.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
data/cards/homestead/H55.webp
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
data/cards/homestead/H56.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
data/cards/homestead/H57.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
data/cards/homestead/H58.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
data/cards/homestead/H59.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 34 KiB |
BIN
data/cards/homestead/H60.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
data/cards/homestead/H61.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
data/cards/homestead/H62.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
data/cards/homestead/H63.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
data/cards/homestead/H64.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/cards/homestead/H65.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
data/cards/homestead/H66.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/cards/homestead/H67.webp
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
data/cards/homestead/H68.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
data/cards/homestead/H69.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 26 KiB |
BIN
data/cards/homestead/H70.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
data/cards/homestead/H71.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
data/cards/homestead/H72.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
data/cards/homestead/H73.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
data/cards/homestead/H74.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
data/cards/homestead/H75.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
data/cards/homestead/H76.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 33 KiB |