diff --git a/service_events.json b/service_events.json index 2dc608a..db5a278 100644 --- a/service_events.json +++ b/service_events.json @@ -1,4 +1,1400 @@ [ + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "tdkhh3hwb", + "timestamp": 1775187681954 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "l6eiwwjbe", + "timestamp": 1775187681936 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "qmi0w9vqv", + "timestamp": 1775187681917 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "9m0n4prqk", + "timestamp": 1775187681899 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "v7bxe3090", + "timestamp": 1775187681609 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "5b3rd5zpq", + "timestamp": 1775187681588 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "31iekb7di", + "timestamp": 1775187680907 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "6d6p07liw", + "timestamp": 1775187680841 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "ifrectvi9", + "timestamp": 1775187657211 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "a22ap9umr", + "timestamp": 1775187655797 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "br7xu4yzx", + "timestamp": 1775186975820 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "9omjmgrfx", + "timestamp": 1775186975803 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "2t28fxbmq", + "timestamp": 1775186975622 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "gkxuhz6wk", + "timestamp": 1775186975597 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "ya0e55ybp", + "timestamp": 1775159681530 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "5zpx5yqr3", + "timestamp": 1775159680125 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "4erwddrst", + "timestamp": 1775159679796 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "0511p4pqx", + "timestamp": 1775159654398 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "g2gsqa082", + "timestamp": 1775159638274 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "t2eok4dic", + "timestamp": 1775159625397 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "e6hmi4ifo", + "timestamp": 1775159625389 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "bomm6932i", + "timestamp": 1775159625383 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "qzfg00epn", + "timestamp": 1775159625377 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "aawe0vr0k", + "timestamp": 1775159625370 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "uo5eyc3fq", + "timestamp": 1775159625364 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "sfmr30zjg", + "timestamp": 1775159625344 + }, + { + "service": "mariadb:10.11.8", + "action": "stop", + "status": "info", + "id": "zpffjoqrc", + "timestamp": 1775159625339 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "7x8rckr1b", + "timestamp": 1775159625331 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "88zer705d", + "timestamp": 1775159625324 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "0i20u0gqr", + "timestamp": 1775159625317 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "0jd280emi", + "timestamp": 1775159625308 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "78saltpdd", + "timestamp": 1775159625300 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "npe7cr0ns", + "timestamp": 1775159625292 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "kfnzcgtiw", + "timestamp": 1775159623063 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "n3xng5h3a", + "timestamp": 1775159581551 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "7ug3zc4y7", + "timestamp": 1775159581517 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "hnivt5g47", + "timestamp": 1775159580267 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "tsrk5604g", + "timestamp": 1775159511257 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "kuzb679r7", + "timestamp": 1775159504691 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "0s6y4ofcl", + "timestamp": 1775159504677 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "nlk4c5w9u", + "timestamp": 1775159476660 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "88w2veyk8", + "timestamp": 1775159475208 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "1pzq13pem", + "timestamp": 1775159441739 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "a77n663rb", + "timestamp": 1775159441715 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "c5a29kb2a", + "timestamp": 1775159441696 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "35t3m5mx8", + "timestamp": 1775159441687 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "5q09yixy8", + "timestamp": 1775159441665 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "gc8ps40we", + "timestamp": 1775159441664 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "gc5t8y7ky", + "timestamp": 1775159440196 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "nj7ppyc82", + "timestamp": 1775159439720 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "a2dz7mfpw", + "timestamp": 1775159439674 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "ht4uv7gzh", + "timestamp": 1775159439643 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "a0892sdy2", + "timestamp": 1775159439621 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "qe6ldue6b", + "timestamp": 1775159439612 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "e8rt09qdh", + "timestamp": 1775159439592 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "i63npf372", + "timestamp": 1775159438353 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "q7f66q575", + "timestamp": 1775159438065 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "ty9a79qrv", + "timestamp": 1775159438047 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "myys694ei", + "timestamp": 1775159437367 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "4di02u0op", + "timestamp": 1775159437314 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "dssv19t8h", + "timestamp": 1775159436835 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "7gl6hfcc8", + "timestamp": 1775159436818 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "f7w7fzkx0", + "timestamp": 1775159434231 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "8tgghiskt", + "timestamp": 1775159434223 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "j67rjh2ua", + "timestamp": 1775159434217 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "yn5133f4o", + "timestamp": 1775159434210 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "bv0saenc8", + "timestamp": 1775159434204 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "5xqqwgf0e", + "timestamp": 1775159434196 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "02oykhkbi", + "timestamp": 1775159434189 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "hijs2t8gt", + "timestamp": 1775159434177 + }, + { + "service": "mariadb:10.11.8", + "action": "stop", + "status": "info", + "id": "yxh9cedox", + "timestamp": 1775159434171 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "1571ltsdm", + "timestamp": 1775159434163 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "owh3qkrpc", + "timestamp": 1775159434153 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "al0xrpz94", + "timestamp": 1775159434147 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "c6jlneyi2", + "timestamp": 1775159434138 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "1sv9zp7g9", + "timestamp": 1775159434130 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "ap8i3227p", + "timestamp": 1775159434116 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "lolpg91wa", + "timestamp": 1775159434114 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "1abudcuaz", + "timestamp": 1775159375741 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "k4k9m2lw5", + "timestamp": 1775159375725 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "rz60hrjtp", + "timestamp": 1775159375708 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "7sjf6xp5w", + "timestamp": 1775159375692 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "i11f8hr42", + "timestamp": 1775159375434 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "6lcatl0pl", + "timestamp": 1775159375406 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "86ghu2cmr", + "timestamp": 1775159374709 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "dua5pah0d", + "timestamp": 1775159374644 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "b0dax1kaw", + "timestamp": 1775159373578 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "kobkgb2sp", + "timestamp": 1775159373570 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "gupqyi0gt", + "timestamp": 1775159373559 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "ofeojranh", + "timestamp": 1775159373553 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "d0tdav7xs", + "timestamp": 1775159373545 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "ixyqpzmgz", + "timestamp": 1775159373537 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "r0j365dbc", + "timestamp": 1775159373530 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "3lxk1w4j0", + "timestamp": 1775159373516 + }, + { + "service": "mariadb:10.11.8", + "action": "stop", + "status": "info", + "id": "4xwhy4skd", + "timestamp": 1775159373512 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "led6h97ez", + "timestamp": 1775159373503 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "7xk70y4j4", + "timestamp": 1775159373496 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "oxk7z9wyt", + "timestamp": 1775159373489 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "lh2mcsfce", + "timestamp": 1775159373481 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "uhkxhggek", + "timestamp": 1775159373475 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "wu3gj636j", + "timestamp": 1775159373463 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "nrx8njw3t", + "timestamp": 1775159373462 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "eaj0lzcv8", + "timestamp": 1775159343177 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "flrcokfkz", + "timestamp": 1775159343161 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "j3050u7r1", + "timestamp": 1775159343144 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "decu77c7i", + "timestamp": 1775159343130 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "u2wg33q01", + "timestamp": 1775159342919 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "5xzpbadwa", + "timestamp": 1775159342897 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "3sz8l1rga", + "timestamp": 1775159342143 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "n9gfbh4bu", + "timestamp": 1775159342088 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "gh4le9li6", + "timestamp": 1775159340823 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "8m8f3ymee", + "timestamp": 1775159340813 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "b0bia0u6i", + "timestamp": 1775159340805 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "cq4hutzi5", + "timestamp": 1775159340799 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "r6ycxixl7", + "timestamp": 1775159340790 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "lmrgxd7ro", + "timestamp": 1775159340782 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "jsaa91sc8", + "timestamp": 1775159340759 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "z7whq2wmv", + "timestamp": 1775159340757 + }, + { + "service": "mariadb:10.11.8", + "action": "stop", + "status": "info", + "id": "41a3oj6hh", + "timestamp": 1775159340752 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "4e1gz2vt5", + "timestamp": 1775159340744 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "lng89p1fe", + "timestamp": 1775159340736 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "a53022yxy", + "timestamp": 1775159340728 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "b6aw4hxld", + "timestamp": 1775159340720 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "09ka41d6b", + "timestamp": 1775159340713 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "3eymywct0", + "timestamp": 1775159340700 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "pa1qnri89", + "timestamp": 1775159340699 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "id3rtmxjf", + "timestamp": 1775159256110 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "54crfx8ar", + "timestamp": 1775159256086 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "xtj0l8xee", + "timestamp": 1775159256058 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "02klygx2g", + "timestamp": 1775159256049 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "jdxxe2nra", + "timestamp": 1775159256042 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "ghbso6gxy", + "timestamp": 1775159256020 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "1wp1gon4b", + "timestamp": 1775159249146 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "j96vv311x", + "timestamp": 1775159249130 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "p2fqm1mqb", + "timestamp": 1775159249113 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "9300vriyt", + "timestamp": 1775159249098 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "jgn41jdo3", + "timestamp": 1775159248908 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "p0pv203b5", + "timestamp": 1775159248881 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "9gx8x1l0k", + "timestamp": 1775159248114 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "svcmo7yfs", + "timestamp": 1775159248049 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "epot8g031", + "timestamp": 1775159245196 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "qb7szy8pj", + "timestamp": 1775159245188 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "21q10d1sw", + "timestamp": 1775159245178 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "nyrzhpizg", + "timestamp": 1775159245172 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "lhcqso529", + "timestamp": 1775159245149 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "j5bxoootl", + "timestamp": 1775159245146 + }, + { + "service": "mariadb:10.11.8", + "action": "stop", + "status": "info", + "id": "r2zrtoeoo", + "timestamp": 1775159245142 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "2fwbzpe9l", + "timestamp": 1775159245133 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "x7p9c2daz", + "timestamp": 1775159245123 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "gnfqh1ngs", + "timestamp": 1775159245114 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "4t1a3xszb", + "timestamp": 1775159245099 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "4fz9e9xz9", + "timestamp": 1775159245097 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "un9x2kbk0", + "timestamp": 1775159107878 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "0wlbp2meq", + "timestamp": 1775159107836 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "7o7lvslg6", + "timestamp": 1775159107493 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "gmi9yn1w9", + "timestamp": 1775159107487 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "xmj7kkvye", + "timestamp": 1775159105632 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "2ffzsgfw5", + "timestamp": 1775159105623 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "hr4jc73qo", + "timestamp": 1775159105250 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "pgkec3ghh", + "timestamp": 1775159105242 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "a3jskjdko", + "timestamp": 1775159105229 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "4jyiudk7i", + "timestamp": 1775159105221 + }, + { + "service": "php:5.6.40", + "action": "start", + "status": "success", + "id": "o4z9hgxro", + "timestamp": 1775159099484 + }, + { + "service": "php:7.4.33", + "action": "start", + "status": "success", + "id": "fbvzowgyg", + "timestamp": 1775159099468 + }, + { + "service": "php:8.2.30", + "action": "start", + "status": "success", + "id": "lt931v989", + "timestamp": 1775159099450 + }, + { + "service": "php:8.5.4", + "action": "start", + "status": "success", + "id": "2dtdc938j", + "timestamp": 1775159099435 + }, + { + "service": "mariadb:11.4.2", + "action": "start", + "status": "success", + "id": "nz2u9ml7o", + "timestamp": 1775159099207 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "8e4yi1ikv", + "timestamp": 1775159099184 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "ypir4t26i", + "timestamp": 1775159098460 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "j1m3jvhem", + "timestamp": 1775159098402 + }, + { + "service": "mariadb:10.11.8", + "action": "exit", + "status": "failure", + "details": "Exit code: 1", + "id": "68wans1pb", + "timestamp": 1775159096442 + }, + { + "service": "mariadb:11.4.2", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "fzf99gaez", + "timestamp": 1775159096153 + }, + { + "service": "php:5.6.40", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "r9xmxsk4x", + "timestamp": 1775159096145 + }, + { + "service": "php:7.4.33", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "25ou1u130", + "timestamp": 1775159096138 + }, + { + "service": "php:8.2.30", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "ugj9qbap6", + "timestamp": 1775159096132 + }, + { + "service": "php:8.5.4", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "n8qnvacfh", + "timestamp": 1775159096126 + }, + { + "service": "apache", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "0r3j64ikj", + "timestamp": 1775159096105 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "a60yjeaxb", + "timestamp": 1775159096104 + }, + { + "service": "mariadb:11.4.2", + "action": "stop", + "status": "info", + "id": "i92r1fi0w", + "timestamp": 1775159096098 + }, + { + "service": "php:5.6.40", + "action": "stop", + "status": "info", + "id": "940akyt32", + "timestamp": 1775159096090 + }, + { + "service": "php:7.4.33", + "action": "stop", + "status": "info", + "id": "46q4br638", + "timestamp": 1775159096082 + }, + { + "service": "php:8.2.30", + "action": "stop", + "status": "info", + "id": "rfya1dn4z", + "timestamp": 1775159096074 + }, + { + "service": "php:8.5.4", + "action": "stop", + "status": "info", + "id": "u5ii2vc8i", + "timestamp": 1775159096067 + }, + { + "service": "apache", + "action": "stop", + "status": "info", + "id": "k40ch2loz", + "timestamp": 1775159096050 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "m4pr5k0ss", + "timestamp": 1775159096049 + }, + { + "service": "mariadb:10.11.8", + "action": "start", + "status": "success", + "id": "sgwb8aw4f", + "timestamp": 1775159093659 + }, + { + "service": "apache", + "action": "start", + "status": "success", + "id": "jfej5nvj1", + "timestamp": 1775159092940 + }, + { + "service": "nginx", + "action": "start", + "status": "success", + "id": "sltqce5fx", + "timestamp": 1775158844546 + }, + { + "service": "nginx", + "action": "exit", + "status": "failure", + "details": "Exit code: null", + "id": "cjtn4lmwa", + "timestamp": 1775158843090 + }, + { + "service": "nginx", + "action": "stop", + "status": "info", + "id": "itqws203g", + "timestamp": 1775158843086 + }, { "service": "nginx", "action": "start", diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts index 5365c2e..009955d 100644 --- a/src/main/ipc/index.ts +++ b/src/main/ipc/index.ts @@ -337,6 +337,26 @@ async function restartApache(): Promise<{ success: boolean; message: string }> { } export function registerIpcHandlers(): void { + console.log('Registering config:template IPC handlers...') + ipcMain.handle('config:template:get', async (_event, templateName: string) => { + try { + console.log('Fetching template:', templateName) + return { success: true, content: configService.getTemplate(templateName) } + } catch (error: any) { + console.error('Failed to get template:', error) + return { success: false, message: error.message } + } + }) + + ipcMain.handle('config:template:save', async (_event, { templateName, content }) => { + try { + configService.saveTemplate(templateName, content) + return { success: true, message: 'Şablon başarıyla kaydedildi.' } + } catch (error: any) { + return { success: false, message: error.message } + } + }) + ipcMain.handle('mariadb:processlist', async (_event, versionId) => { try { return await mariaDbManagerService.getProcessList(versionId) diff --git a/src/main/services/ConfigService.ts b/src/main/services/ConfigService.ts index 859076f..b162445 100644 --- a/src/main/services/ConfigService.ts +++ b/src/main/services/ConfigService.ts @@ -71,6 +71,26 @@ export class ConfigService { return path.join(this.configDir, targetName) } + getTemplate(templateName: string): string { + const templatePath = path.join(this.templateDir, templateName) + if (!fs.existsSync(templatePath)) { + throw new Error(`Template not found: ${templatePath}`) + } + return fs.readFileSync(templatePath, 'utf-8') + } + + saveTemplate(templateName: string, content: string): void { + const templatePath = path.join(this.templateDir, templateName) + const backupPath = `${templatePath}.bak` + + // Simple backup + if (fs.existsSync(templatePath)) { + fs.copyFileSync(templatePath, backupPath) + } + + fs.writeFileSync(templatePath, content) + } + getSettings(): any { try { if (fs.existsSync(this.settingsPath)) { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 3786169..b26bafd 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -71,7 +71,6 @@ import { Close as CloseIcon, ContentCopy as ContentCopyIcon, OpenInNew as OpenIcon, - Restore as ResetIcon, Tune as TuningIcon, History as HistoryIcon, MenuBook as GuideIcon, @@ -90,6 +89,7 @@ import ServerTuning from './components/ServerTuning' import ServiceEventMonitor from './components/ServiceEventMonitor' import UserGuide from './components/UserGuide' import ProjectManager from './components/ProjectManager/ProjectManager' +import DashboardManager from './components/Dashboard/DashboardManager' declare global { interface Window { @@ -135,7 +135,6 @@ function App(): JSX.Element { const [projectSearch, setProjectSearch] = useState('') const [cliConfig, setCliConfig] = useState({ enabled: true, defaultPhp: '', defaultMariaDb: '', binDir: '' }) const [settingsTab, setSettingsTab] = useState(0) - const [dashboardTab, setDashboardTab] = useState(0) const [projects, setProjects] = useState([]) const [phpVersions, setPhpVersions] = useState([]) const [mariaDbVersions, setMariaDbVersions] = useState([]) @@ -190,6 +189,11 @@ function App(): JSX.Element { const [selectedProjectId, setSelectedProjectId] = useState(null) const [projectDetailTab, setProjectDetailTab] = useState(0) + const handleSelectProject = (projectId: string) => { + setSelectedProjectId(projectId) + setActiveTab('projects') + } + const parseNginxError = (message: string) => { const match = message.match(/in (.*):(\d+)/) if (!match) return null @@ -270,9 +274,10 @@ function App(): JSX.Element { } const fetchApacheVersions = async () => { - if (!window.api || !window.api.getApacheVersions) return - const v = await window.api.getApacheVersions() - setApacheVersions(v || []) + if (window.api && window.api.getApacheVersions) { + const list = await window.api.getApacheVersions() + setApacheVersions(list || []) + } } const fetchLogs = async (service: string) => { @@ -385,6 +390,49 @@ function App(): JSX.Element { } }, [logs, logDialogOpen]) + const handleOpenNginxConfig = async () => { + if (window.api && window.api.invoke) { + const config = await window.api.invoke('nginx:config:get') + setNginxConfig(config) + setIsNginxConfigOpen(true) + } + } + + const handleSaveNginxConfig = async () => { + if (window.api && window.api.invoke) { + const result = await window.api.invoke('nginx:config:save', nginxConfig) + if (result.success) { + Swal.fire({ title: t('common.success'), text: t('server.nginx.config_saved'), icon: 'success', background: '#1e1e1e', color: '#fff' }) + setIsNginxConfigOpen(false) + } + } + } + + const handleOpenApacheConfig = async () => { + if (window.api && window.api.invoke) { + const config = await window.api.invoke('apache:config:get') + setApacheConfig(config) + setIsApacheConfigOpen(true) + } + } + + const handleSaveApacheConfig = async () => { + if (window.api && window.api.invoke) { + const result = await window.api.invoke('apache:config:save', apacheConfig) + if (result.success) { + Swal.fire({ title: t('common.success'), text: t('server.apache.config_saved'), icon: 'success', background: '#1e1e1e', color: '#fff' }) + setIsApacheConfigOpen(false) + } + } + } + + const handleTestApacheConfig = async () => { + if (window.api && window.api.invoke) { + const result = await window.api.invoke('apache:config:test') + Swal.fire({ title: result.success ? t('common.success') : t('common.error'), text: result.message, icon: result.success ? 'success' : 'error', background: '#1e1e1e', color: '#fff' }) + } + } + const handleSelectPath = async () => { if (window.api && window.api.selectDirectory) { const pathStr = await window.api.selectDirectory() @@ -396,76 +444,6 @@ function App(): JSX.Element { } } - const handleToggleService = async (service: string) => { - if (!window.api) return - - const isStarting = ((status[service] as any)?.status || status[service] || 'stopped') === 'stopped' - if (isStarting) { - setStatus(prev => ({ ...prev, [service]: { status: 'starting' } })) - } - - const result = ((status[service] as any)?.status || status[service] || 'stopped') === 'running' - ? await window.api.stopService(service) - : await window.api.startService(service) - - // Refresh status after operation - fetchStatus() - - if (!result.success) { - Swal.fire({ - title: t('common.error'), - text: result.message, - icon: 'error', - confirmButtonText: t('common.ok'), - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#153E5E', - customClass: { - popup: 'swal2-dark-popup' - } - }) - } else { - setNotification({ - open: true, - message: result.message, - severity: 'success' - }) - } - } - - const handleOpenLogs = async (service: string) => { - setSelectedService(service) - setLogDialogOpen(true) - await fetchLogs(service) - } - - const handleResetData = async (service: string) => { - const confirmResult = await Swal.fire({ - title: t('common.reset_confirm_title'), - text: t('common.reset_confirm_text', { service }), - icon: 'warning', - showCancelButton: true, - confirmButtonText: t('common.reset_btn'), - cancelButtonText: t('common.cancel'), - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#d33', - cancelButtonColor: '#3085d6' - }) - - if (confirmResult.isConfirmed) { - const result = await window.api.invoke('services:reset-data', service) - Swal.fire({ - title: result.success ? t('common.success') : t('common.error'), - text: result.message, - icon: result.success ? 'success' : 'error', - background: '#1e1e1e', - color: '#fff' - }) - fetchStatus() - } - } - const handleSaveSettings = async () => { if (window.api && window.api.saveSettings) { const result = await window.api.saveSettings(settings) @@ -532,74 +510,6 @@ function App(): JSX.Element { return `${Math.round(mb)} MB` } - const getStatusChip = (s: string | { status: string, cpu?: number, memory?: number }) => { - const state = typeof s === 'string' ? s : s.status - - if (state === 'starting') { - return } /> - } - if (state === 'stopping') { - return } /> - } - const color = state === 'running' ? 'success' : state === 'stopped' ? 'error' : 'warning' - - return - } - - const ResourceMonitor = ({ cpu, memory }: { cpu?: number; memory?: number }) => { - if (cpu === undefined && memory === undefined) return null; - - const ramMB = memory ? Math.round(memory / (1024 * 1024)) : 0; - const ramLimit = 1024; // 1GB scale for visual - const cpuValue = cpu || 0; - const ramPercent = Math.min((ramMB / ramLimit) * 100, 100); - - return ( - - - - CPU - {cpuValue}% - - - - - - RAM - {formatMemory(memory as number)} - - - - - ); - }; - - const handleAddProject = async () => { if (!window.api) return let result; @@ -638,77 +548,11 @@ function App(): JSX.Element { } } - const handleOpenNginxConfig = async () => { + const handleOpenProcessList = async (id: string) => { + setSelectedMariaDbId(id) + setIsProcessListOpen(true) if (window.api && window.api.invoke) { - const config = await window.api.invoke('nginx:config:get') - setNginxConfig(config) - setIsNginxConfigOpen(true) - } - } - - const handleSaveNginxConfig = async () => { - if (window.api && window.api.invoke) { - const result = await window.api.invoke('nginx:config:save', nginxConfig) - if (result.success) { - Swal.fire({ - title: t('common.success'), - text: t('server.nginx.config_saved'), - icon: 'success', - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#153E5E', - customClass: { popup: 'swal2-dark-popup' } - }) - setIsNginxConfigOpen(false) - } - } - } - - const handleOpenApacheConfig = async () => { - if (window.api && window.api.invoke) { - const config = await window.api.invoke('apache:config:get') - setApacheConfig(config) - setIsApacheConfigOpen(true) - } - } - - const handleSaveApacheConfig = async () => { - if (window.api && window.api.invoke) { - const result = await window.api.invoke('apache:config:save', apacheConfig) - if (result.success) { - Swal.fire({ - title: t('common.success'), - text: t('server.apache.config_saved'), - icon: 'success', - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#153E5E', - customClass: { popup: 'swal2-dark-popup' } - }) - setIsApacheConfigOpen(false) - } - } - } - - const handleTestApacheConfig = async () => { - if (window.api && window.api.invoke) { - const result = await window.api.invoke('apache:config:test') - const formattedMessage = result.message - .replace(/failed/g, 'failed') - .replace(/successful/g, 'successful') - - Swal.fire({ - title: result.success ? 'Başarılı' : 'Yapılandırma Hatası', - html: ` -
- ${formattedMessage} -
- `, - icon: result.success ? 'success' : 'error', - background: '#1e1e1e', - color: '#fff', - width: '600px' - }) + await fetchProcessList(id) } } @@ -849,10 +693,6 @@ function App(): JSX.Element { setIsPhpExtensionsOpen(true) } - const handleOpenProcessList = async (id: string) => { - setSelectedMariaDbId(id) - setActiveTab('db_monitor') - } const fetchProcessList = async (id: string) => { if (!window.api) return @@ -1530,217 +1370,16 @@ function App(): JSX.Element { )} {activeTab === 'dashboard' && ( - <> - - setDashboardTab(v)} textColor="primary" indicatorColor="primary"> - - - - - - - - - - {/* Nginx Box */} - {(dashboardTab === 0 || dashboardTab === 1) && ( - - - - - {getStatusChip(status.nginx)} - - Nginx - Port: {settings.nginxPort} - - - - handleOpenLogs('nginx')} title={t('diagnostics.logs')} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}> - - - - - - { - window.api.invoke('services:reload', 'nginx').then((res: any) => { - Swal.fire({ - title: res.success ? t('common.success') : t('common.error'), - text: res.message, - icon: res.success ? 'success' : 'error', - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#153E5E', - customClass: { popup: 'swal2-dark-popup' } - }) - }) - }} - title={t('server.nginx.save_reload')} - size="small" - disabled={status.nginx?.status !== 'running'} - sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'primary.main' } }} - > - - - - handleToggleService('nginx')} - disabled={status.nginx?.status === 'starting'} - /> - - - - )} - - {/* Apache Box */} - {(dashboardTab === 0 || dashboardTab === 2) && ( - - - - - {getStatusChip(status.apache)} - - Apache - Port: {settings.apachePort} - - - - handleOpenLogs('apache')} title={t('diagnostics.logs')} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}> - - - - - - { - window.api.invoke('services:reload', 'apache').then((res: any) => { - Swal.fire({ - title: res.success ? t('common.success') : t('common.error'), - text: res.message, - icon: res.success ? 'success' : 'error', - background: '#1e1e1e', - color: '#fff', - confirmButtonColor: '#153E5E', - customClass: { popup: 'swal2-dark-popup' } - }) - }) - }} - title={t('server.apache.save_reload')} - size="small" - disabled={status.apache?.status !== 'running'} - sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'primary.main' } }} - > - - - - handleToggleService('apache')} - disabled={status.apache?.status === 'starting'} - /> - - - - )} - - {/* PHP Boxes */} - {(dashboardTab === 0 || dashboardTab === 3) && installedPhpVersions.map(v => ( - - - - - {getStatusChip(status[`php:${v.version}`] || { status: 'stopped' })} - - PHP {v.version} - Port: {v.port || '?'} - - - handleOpenLogs(`php:${v.version}`)} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}> - - - handleToggleService(`php:${v.version}`)} - disabled={status[`php:${v.version}`]?.status === 'starting'} - /> - - - - ))} - - {/* MariaDB Boxes */} - {(dashboardTab === 0 || dashboardTab === 4) && mariaDbVersions.filter(v => v.status === 'installed').map(v => ( - - - - - {getStatusChip(status[`mariadb:${v.version}`] || { status: 'stopped' })} - - MariaDB {v.version} - Port: {settings.mariaDbPorts?.[v.id] || v.port} - - - - handleOpenLogs(`mariadb:${v.version}`)} title={t('diagnostics.logs')} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}> - - - handleOpenProcessList(v.id)} title={t('mariadb_process_monitor.title')} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'primary.main' } }}> - - - handleResetData(`mariadb:${v.version}`)} title={t('common.reset')} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'error.main' } }}> - - - - handleToggleService(`mariadb:${v.version}`)} - disabled={status[`mariadb:${v.version}`]?.status === 'starting'} - /> - - - - ))} - - + )} {activeTab === 'db_monitor' && ( diff --git a/src/renderer/src/components/Dashboard/DashboardDetails.tsx b/src/renderer/src/components/Dashboard/DashboardDetails.tsx new file mode 100644 index 0000000..14c403d --- /dev/null +++ b/src/renderer/src/components/Dashboard/DashboardDetails.tsx @@ -0,0 +1,462 @@ +import { + Box, + Typography, + Tabs, + Tab, + Paper, + Grid, + IconButton, + Button, + List, + ListItem, + ListItemText, + ListItemSecondaryAction, + Divider, + LinearProgress, + CircularProgress, + Stack +} from '@mui/material' +import { + Refresh as RefreshIcon, + PlayArrow as StartIcon, + Stop as StopIcon, + OpenInNew as OpenIcon, + Save as SaveIcon, + Folder as ProjectIcon, + Language as WebIcon, + Dns as ServerIcon, + Code as PhpIcon, + Storage as DbIcon +} from '@mui/icons-material' +import { useState, useEffect, useRef } from 'react' +import 'prismjs/themes/prism-tomorrow.css' +import 'prismjs/components/prism-nginx' +import 'prismjs/components/prism-apacheconf' +import 'prismjs/components/prism-ini' +import Editor from 'react-simple-code-editor' +import Prism from 'prismjs' +import Swal from 'sweetalert2' + +interface DashboardDetailsProps { + serviceId: string | null; + status: any; + settings: any; + projects: any[]; + t: any; + onToggleService: (id: string) => void; + onReloadService: (id: string) => void; + onSelectProject: (id: string) => void; +} + +export default function DashboardDetails({ + serviceId, + status, + settings, + projects, + t, + onToggleService, + onReloadService, + onSelectProject +}: DashboardDetailsProps) { + const [activeTab, setActiveTab] = useState(0); + const [configContent, setConfigContent] = useState(''); + const [projectConfigContent, setProjectConfigContent] = useState(''); + const [isLoadingConfig, setIsLoadingConfig] = useState(false); + const [logs, setLogs] = useState([]); + const logEndRef = useRef(null); + + const getServiceType = () => { + if (!serviceId) return null; + if (serviceId === 'nginx') return 'nginx'; + if (serviceId === 'apache') return 'apache'; + if (serviceId.startsWith('php:')) return 'php'; + if (serviceId.startsWith('mariadb:')) return 'mariadb'; + return null; + }; + + const serviceType = getServiceType(); + + const getTemplateName = (): string => { + if (serviceId === 'nginx') return 'nginx.conf.template'; + if (serviceType === 'apache') return 'httpd.conf.template'; + if (serviceType === 'php') return 'php.ini.template'; + if (serviceType === 'mariadb') return 'mariadb.ini.template'; + return ''; + }; + + const getProjectTemplateNames = () => { + if (serviceId === 'nginx' || serviceType === 'php') return ['nginx_project_location.conf.template']; + if (serviceId === 'apache') return ['apache_project.conf.template']; + return []; + }; + + const fetchConfig = async (templateName: string, setter: (v: string) => void) => { + if (!templateName) return; + setIsLoadingConfig(true); + try { + const res = await window.api.invoke('config:template:get', templateName); + if (res && res.success) { + setter(res.content || ''); + } else { + console.error('Failed to fetch config:', res?.message); + setter(''); + } + } catch (error) { + console.error('Error fetching config:', error); + setter(''); + } finally { + setIsLoadingConfig(false); + } + }; + + const saveConfig = async (templateName: string, content: string) => { + const res = await window.api.invoke('config:template:save', { templateName, content }); + if (res.success) { + Swal.fire({ + title: t('common.success'), + text: res.message, + icon: 'success', + background: '#1e1e1e', + color: '#fff' + }); + } else { + Swal.fire({ + title: t('common.error'), + text: res.message, + icon: 'error', + background: '#1e1e1e', + color: '#fff' + }); + } + }; + + const fetchLogs = async () => { + if (!serviceId) return; + const res = await window.api.invoke('services:logs', serviceId); + setLogs(res || []); + }; + + const getHighlightLanguage = (templateName: string) => { + if (!templateName) return Prism.languages.clike; + if (templateName.includes('nginx')) return Prism.languages.nginx; + if (templateName.includes('httpd') || templateName.includes('apache')) return Prism.languages.apacheconf; + if (templateName.includes('.ini') || templateName.includes('.conf')) return Prism.languages.ini; + return Prism.languages.clike; + }; + + const getHighlightLabel = (templateName: string) => { + if (!templateName) return 'clike'; + if (templateName.includes('nginx')) return 'nginx'; + if (templateName.includes('httpd') || templateName.includes('apache')) return 'apacheconf'; + if (templateName.includes('.ini') || templateName.includes('.conf')) return 'ini'; + return 'clike'; + }; + + useEffect(() => { + if (activeTab === 1) fetchConfig(getTemplateName(), setConfigContent); + if (activeTab === 2) { + const templates = getProjectTemplateNames(); + if (templates.length > 0) fetchConfig(templates[0], setProjectConfigContent); + } + if (activeTab === 3) { + fetchLogs(); + const interval = setInterval(fetchLogs, 3000); + return () => clearInterval(interval); + } + return undefined; + }, [activeTab, serviceId]); + + useEffect(() => { + if (activeTab === 3 && logEndRef.current) { + logEndRef.current.scrollIntoView({ behavior: 'smooth' }); + } + }, [logs, activeTab]); + + if (!serviceId) { + return ( + + {t('dashboard.select_service', 'Lütfen bir servis seçin')} + + ); + } + + const currentStatus = status[serviceId] || { status: 'stopped' }; + const isRunning = currentStatus.status === 'running'; + + const serviceProjects = projects.filter(p => { + if (serviceId === 'nginx') return !p.serverType || p.serverType === 'nginx'; + if (serviceId === 'apache') return p.serverType === 'apache'; + if (serviceType === 'php') return p.phpVersion === serviceId.split(':')[1]; + if (serviceType === 'mariadb') return true; // MariaDB is shared (or filter if multi-instance) + return false; + }); + + const ResourceMonitor = ({ cpu, memory }: { cpu?: number; memory?: number }) => ( + + + + CPU + {cpu || 0}% + + + + + + RAM + + {memory ? `${Math.round(memory / (1024 * 1024))} MB` : '0 MB'} + + + + + + ); + + return ( + + + + {serviceType === 'nginx' && } + {serviceType === 'apache' && } + {serviceType === 'php' && } + {serviceType === 'mariadb' && } + + + {serviceId.toUpperCase()} + + {isRunning ? t('common.running', 'Çalışıyor') : t('common.stopped', 'Durduruldu')} + + + + {isRunning && ( + onReloadService(serviceId)} sx={{ bgcolor: 'rgba(57, 167, 255, 0.1)', color: 'primary.main' }}> + + + )} + + + + + + setActiveTab(v)}> + + + {(serviceId === 'nginx' || serviceId === 'apache' || serviceType === 'php') && ( + + )} + + + + + + + {activeTab === 0 && ( + + + SYSTEM STATS + + + + + + SERVICE INFO + + + + Port + + {currentStatus.port || (() => { + if (serviceId === 'nginx') return settings.nginxPort; + if (serviceId === 'apache') return settings.apachePort; + if (serviceType === 'php') return settings.phpPort; + if (serviceType === 'mariadb') { + const verId = serviceId.split(':')[1]; + return (settings.mariaDbPorts && settings.mariaDbPorts[verId]) || settings.mariaDbPort; + } + return 'n/a'; + })()} + + + + + Status + + {currentStatus.status.toUpperCase()} + + + + + + + )} + + {activeTab === 1 && ( + + + + {getTemplateName().toUpperCase()} + + + + + {isLoadingConfig ? ( + + ) : ( + + Prism.highlight(code, getHighlightLanguage(getTemplateName()), getHighlightLabel(getTemplateName()))} + padding={20} + style={{ + fontFamily: '"Fira Code", "Consolas", monospace', + fontSize: '14px', + minHeight: '100%', + outline: 'none' + }} + textareaClassName="editor-textarea" + /> + + )} + + + )} + + {activeTab === 2 && ( + + + + {getProjectTemplateNames()[0]?.toUpperCase()} + + + + + {isLoadingConfig ? ( + + ) : ( + + Prism.highlight(code, getHighlightLanguage(getProjectTemplateNames()[0]), getHighlightLabel(getProjectTemplateNames()[0]))} + padding={20} + style={{ + fontFamily: '"Fira Code", "Consolas", monospace', + fontSize: '14px', + minHeight: '100%', + outline: 'none' + }} + textareaClassName="editor-textarea" + /> + + )} + + + )} + + {activeTab === 3 && ( + + {logs.map((log, i) => ( + + {log} + + ))} +
+ + )} + + {activeTab === 4 && ( + + + {serviceProjects.length === 0 ? ( + {t('projects.empty')} + ) : ( + serviceProjects.map((p, idx) => ( + + + + + + onSelectProject(p.id)} color="primary"> + + + + + {idx < serviceProjects.length - 1 && } + + )) + )} + + + )} + + + + ); +} diff --git a/src/renderer/src/components/Dashboard/DashboardManager.tsx b/src/renderer/src/components/Dashboard/DashboardManager.tsx new file mode 100644 index 0000000..a72d6fe --- /dev/null +++ b/src/renderer/src/components/Dashboard/DashboardManager.tsx @@ -0,0 +1,89 @@ +import { Box } from '@mui/material' +import DashboardSidebar from './DashboardSidebar' +import DashboardDetails from './DashboardDetails' +import { useState } from 'react' +import Swal from 'sweetalert2' + +interface DashboardManagerProps { + status: any; + settings: any; + projects: any[]; + phpVersions: any[]; + mariaDbVersions: any[]; + t: any; + onFetchStatus: () => void; + onSelectProject: (projectId: string) => void; +} + +export default function DashboardManager({ + status, + settings, + projects, + phpVersions, + mariaDbVersions, + t, + onFetchStatus, + onSelectProject +}: DashboardManagerProps) { + const [selectedServiceId, setSelectedServiceId] = useState('nginx'); + + const handleToggleService = async (service: string) => { + if (!window.api) return; + + const currentStatus = status[service]?.status || 'stopped'; + const isRunning = currentStatus === 'running'; + + const result = isRunning + ? await window.api.stopService(service) + : await window.api.startService(service); + + if (result && !result.success) { + Swal.fire({ + title: t('common.error'), + text: result.message, + icon: 'error', + background: '#1e1e1e', + color: '#fff' + }); + } + onFetchStatus(); + }; + + const handleReloadService = async (service: string) => { + if (!window.api) return; + const result = await window.api.invoke('services:reload', service); + + Swal.fire({ + title: result && result.success ? t('common.success') : t('common.error'), + text: result ? result.message : 'Error', + icon: result && result.success ? 'success' : 'error', + background: '#1e1e1e', + color: '#fff' + }); + + onFetchStatus(); + }; + + return ( + + + + + ); +} diff --git a/src/renderer/src/components/Dashboard/DashboardSidebar.tsx b/src/renderer/src/components/Dashboard/DashboardSidebar.tsx new file mode 100644 index 0000000..660fe24 --- /dev/null +++ b/src/renderer/src/components/Dashboard/DashboardSidebar.tsx @@ -0,0 +1,140 @@ +import { + Box, + Typography, + List, + ListItemButton, + Chip, + CircularProgress +} from '@mui/material' +import { + Language as WebIcon, + Dns as ServerIcon, + Code as PhpIcon, + Storage as DbIcon +} from '@mui/icons-material' + +interface DashboardSidebarProps { + status: any; + phpVersions: any[]; + mariaDbVersions: any[]; + selectedServiceId: string | null; + setSelectedServiceId: (v: string | null) => void; + t: any; +} + +export default function DashboardSidebar({ + status, + phpVersions, + mariaDbVersions, + selectedServiceId, + setSelectedServiceId, + t +}: DashboardSidebarProps) { + + const installedPhp = phpVersions.filter(v => v.status === 'installed'); + const installedMariaDb = mariaDbVersions.filter(v => v.status === 'installed'); + + const getStatusInfo = (service: string) => { + const state = typeof status[service] === 'string' ? status[service] : status[service]?.status || 'stopped'; + const color = state === 'running' ? 'success' : state === 'stopped' ? 'error' : 'warning'; + return { state, color }; + }; + + const ServiceItem = ({ id, label, icon: Icon, serviceKey }: { id: string, label: string, icon: any, serviceKey: string }) => { + const { state } = getStatusInfo(serviceKey); + const isRunning = state === 'running'; + const isStarting = state === 'starting' || state === 'stopping'; + + return ( + setSelectedServiceId(id)} + sx={{ + borderRadius: 2, + mb: 0.5, + border: selectedServiceId === id ? '1px solid rgba(57, 167, 255, 0.3)' : '1px solid transparent', + '&.Mui-selected': { bgcolor: 'rgba(57, 167, 255, 0.08)' } + }} + > + + + + + {label} + + + + {isStarting && } + + + + ); + }; + + return ( + + + + {t('dashboard.services', 'Servisler')} + + + + + + WEB SERVERS + + + + + + + + PHP VERSIONS + + + {installedPhp.map(v => ( + + ))} + + + + MARIADB VERSIONS + + + {installedMariaDb.map(v => ( + + ))} + + + + ); +}