Skip to content

Commit 86f04b5

Browse files
authored
Merge pull request #56 from Sandro642/feature/web-impl
Implement web dashboard for ConnectLib: add DataController, Request, …
2 parents 9434657 + db1eb51 commit 86f04b5

13 files changed

Lines changed: 1241 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Changelog:
5252
- [0.2.6.4-STABLE]: Added asynchronous job execution, allowing you to run tasks in the background without blocking your main application thread.
5353
- [0.2.7.2-STABLE]: Remove implementation Project Reactor
5454
- [0.2.9-STABLE]: Added support query variables in routes, allowing you to pass parameters directly in the URL.
55+
- [0.4.0-STABLE]: Web implementation, now you can have a dashboard to see your connectors and jobs.
5556
```
5657

5758
---

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = 'fr.sandro642.github'
8-
version = '0.3.9.3-STABLE'
8+
version = '0.4.0-STABLE'
99

1010
// Générer une classe de version automatiquement
1111
task generateVersionClass {

src/main/java/fr/sandro642/github/ConnectLib.java

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
import fr.sandro642.github.misc.*;
99
import fr.sandro642.github.jobs.JobGetInfos;
1010
import fr.sandro642.github.enums.ResourceType;
11+
import fr.sandro642.github.spring.Application;
12+
import fr.sandro642.github.spring.controller.DataController;
1113
import fr.sandro642.github.update.RetrieveLastVersion;
1214

15+
import java.util.ArrayList;
1316
import java.util.HashMap;
17+
import java.util.List;
1418
import java.util.Map;
1519

1620
/**
@@ -38,18 +42,25 @@ public class ConnectLib {
3842
private static LangManager langManager;
3943
private static RetrieveLastVersion rlv;
4044

45+
private static boolean isInitialized = false;
46+
47+
private static List<String> enumNames = new ArrayList<>();
48+
private static List<String> enumUrls = new ArrayList<>();
49+
private static Map<Enum<?>, String> routesEnums = new HashMap<>();
50+
4151
/**
4252
* Init the ConnectLib with the specified resource type and routes.
4353
* @param resourceType the type of resource to initialize
4454
* @param routes the routes to be used in the ConnectLib
4555
*/
46-
public void Init(ResourceType resourceType, LangType langType, Class<? extends Enum<?>>... routes) {
56+
public ConnectLib Init(ResourceType resourceType, LangType langType, Class<? extends Enum<?>>... routes) {
4757
try {
4858
logger = new Logger();
4959
storeAndRetrieve = new StoreAndRetrieve();
5060
yamlUtils = new YamlUtils();
5161
logs = new Logs();
5262
rlv = new RetrieveLastVersion();
63+
isInitialized = true;
5364

5465
rlv.isLatestVersion();
5566

@@ -59,6 +70,21 @@ public void Init(ResourceType resourceType, LangType langType, Class<? extends E
5970

6071
langManager = new LangManager();
6172

73+
for (Class<? extends Enum<?>> route : routes) {
74+
if (route == null) {
75+
Logger().ERROR(langManager.getMessage(CategoriesType.CONNECTLIB_CLASS, "initialise.routeclass"));
76+
continue;
77+
}
78+
79+
Map<Enum<?>, String> converted = EnumLoader.convertRouteImport(route);
80+
if (converted != null && !converted.isEmpty()) {
81+
routesEnums.putAll(converted);
82+
for (Map.Entry<Enum<?>, String> entry : converted.entrySet()) {
83+
enumNames.add(entry.getKey().name());
84+
enumUrls.add(entry.getValue());
85+
}
86+
}
87+
}
6288

6389

6490
Map<Enum<?>, String> routesEnums = new HashMap<>();
@@ -85,6 +111,32 @@ public void Init(ResourceType resourceType, LangType langType, Class<? extends E
85111
} catch (Exception e) {
86112
Logger().ERROR(langManager.getMessage(CategoriesType.CONNECTLIB_CLASS, "initialise.catcherror", Map.of("exception", e.getMessage())));
87113
}
114+
return this;
115+
}
116+
117+
/**
118+
* Get the routes map.
119+
* @return a map of route names to their corresponding paths
120+
*/
121+
public Map<String, String> getRoutesMap() {
122+
return new HashMap<>(routes);
123+
}
124+
125+
/**
126+
* Check if the ConnectLib supports web services.
127+
* This method starts the Spring application.
128+
*/
129+
public ConnectLib webServices() {
130+
SpringApp().startApplication().subscribe();
131+
return this;
132+
}
133+
134+
/**
135+
* Check if the ConnectLib is initialized.
136+
* @return true if initialized, false otherwise
137+
*/
138+
public boolean isInitialized() {
139+
return isInitialized;
88140
}
89141

90142
/**
@@ -160,7 +212,7 @@ public HookManager HookManager() {
160212

161213
/**
162214
* Return the instance of LangSupport.
163-
* @return LangSupport instance
215+
* @return LangSupport instance²
164216
*/
165217
public LangSupport LangSupport() {
166218
return LangSupport.getInstance();
@@ -174,4 +226,12 @@ public LangSupport LangSupport() {
174226
public LangManager LangManager() {
175227
return langManager;
176228
}
229+
230+
/**
231+
* Return the instance of Application.
232+
* @return Application instance
233+
*/
234+
public Application SpringApp() {
235+
return Application.getInstance();
236+
}
177237
}

src/main/java/fr/sandro642/github/api/ApiClient.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import fr.sandro642.github.ConnectLib;
44
import fr.sandro642.github.enums.lang.CategoriesType;
5+
import fr.sandro642.github.spring.controller.DataController;
6+
import fr.sandro642.github.spring.dto.Request;
57
import org.springframework.web.reactive.function.client.WebClient;
68
import reactor.core.publisher.Mono;
79
import reactor.core.scheduler.Schedulers;
@@ -44,13 +46,19 @@ public class ApiClient extends ApiFactory {
4446
*/
4547
private final ApiFactory apiFactory = new ApiFactory();
4648

49+
/**
50+
* baseUrl is a static string that holds the base URL for the API.
51+
* It is initialized in the constructor and used for making requests.
52+
*/
53+
private static String baseUrl;
54+
4755
/**
4856
* Constructor for ApiClient.
4957
* It initializes the WebClient with the base URL from the ConnectLib configuration.
5058
* If the base URL is not found, it throws a RuntimeException.
5159
*/
5260
public ApiClient(String baseUrlLambda) {
53-
String baseUrl = baseUrlLambda;
61+
baseUrl = baseUrlLambda;
5462

5563
if (baseUrl == null) {
5664
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "construct.urlbase"));
@@ -69,6 +77,8 @@ public ApiClient(String baseUrlLambda) {
6977
public Mono<ApiFactory> callAPIGet(String routeName) {
7078
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.get", Map.of("routename", routeName)));
7179

80+
Request r = DataController.getInstance().createRequest(routeName, baseUrl);
81+
7282
record ResponseData(int statusCode, String body) {}
7383

7484
return webClient.get()
@@ -80,6 +90,13 @@ record ResponseData(int statusCode, String body) {}
8090
.subscribeOn(Schedulers.boundedElastic())
8191
.doOnNext(responseData -> {
8292
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.threadinuse", "thread", Thread.currentThread().getName()));
93+
94+
String newStatus = (responseData.statusCode() >= 200 && responseData.statusCode() < 300) ? "success" : "error";
95+
try {
96+
DataController.getInstance().updateRequestStatus(r.getId(), newStatus);
97+
} catch (Exception e) {
98+
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "general.error", Map.of("method", "GET", "exception", e.getMessage())));
99+
}
83100
})
84101
.map(responseData -> {
85102
apiFactory.setStatusCode(responseData.statusCode());
@@ -99,6 +116,8 @@ record ResponseData(int statusCode, String body) {}
99116
public Mono<ApiFactory> callAPIPost(String routeName, Map<String, Object> body) {
100117
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.post", Map.of("routename", routeName)));
101118

119+
Request r = DataController.getInstance().createRequest(routeName, baseUrl);
120+
102121
record ResponseData(int statusCode, String body) {}
103122

104123
return webClient.post()
@@ -111,6 +130,13 @@ record ResponseData(int statusCode, String body) {}
111130
.subscribeOn(Schedulers.boundedElastic())
112131
.doOnNext(responseData -> {
113132
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.threadinuse", "thread", Thread.currentThread().getName()));
133+
134+
String newStatus = (responseData.statusCode() >= 200 && responseData.statusCode() < 300) ? "success" : "error";
135+
try {
136+
DataController.getInstance().updateRequestStatus(r.getId(), newStatus);
137+
} catch (Exception e) {
138+
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "general.error", Map.of("method", "GET", "exception", e.getMessage())));
139+
}
114140
})
115141
.map(responseData -> {
116142
apiFactory.setStatusCode(responseData.statusCode());
@@ -130,6 +156,8 @@ record ResponseData(int statusCode, String body) {}
130156
public Mono<ApiFactory> callAPIPut(String routeName, Map<String, Object> body) {
131157
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.put", Map.of("routename", routeName)));
132158

159+
Request r = DataController.getInstance().createRequest(routeName, baseUrl);
160+
133161
record ResponseData(int statusCode, String body) {}
134162

135163
return webClient.put()
@@ -142,6 +170,13 @@ record ResponseData(int statusCode, String body) {}
142170
.subscribeOn(Schedulers.boundedElastic())
143171
.doOnNext(responseData -> {
144172
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.threadinuse", "thread", Thread.currentThread().getName()));
173+
174+
String newStatus = (responseData.statusCode() >= 200 && responseData.statusCode() < 300) ? "success" : "error";
175+
try {
176+
DataController.getInstance().updateRequestStatus(r.getId(), newStatus);
177+
} catch (Exception e) {
178+
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "general.error", Map.of("method", "GET", "exception", e.getMessage())));
179+
}
145180
})
146181
.map(responseData -> {
147182
apiFactory.setStatusCode(responseData.statusCode());
@@ -161,6 +196,8 @@ record ResponseData(int statusCode, String body) {}
161196
public Mono<ApiFactory> callAPIPatch(String routeName, Map<String, Object> body) {
162197
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.patch", Map.of("routename", routeName)));
163198

199+
Request r = DataController.getInstance().createRequest(routeName, baseUrl);
200+
164201
record ResponseData(int statusCode, String body) {}
165202

166203
return webClient.patch()
@@ -173,6 +210,13 @@ record ResponseData(int statusCode, String body) {}
173210
.subscribeOn(Schedulers.boundedElastic())
174211
.doOnNext(responseData -> {
175212
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.threadinuse", "thread", Thread.currentThread().getName()));
213+
214+
String newStatus = (responseData.statusCode() >= 200 && responseData.statusCode() < 300) ? "success" : "error";
215+
try {
216+
DataController.getInstance().updateRequestStatus(r.getId(), newStatus);
217+
} catch (Exception e) {
218+
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "general.error", Map.of("method", "GET", "exception", e.getMessage())));
219+
}
176220
})
177221
.map(responseData -> {
178222
apiFactory.setStatusCode(responseData.statusCode());
@@ -191,6 +235,8 @@ record ResponseData(int statusCode, String body) {}
191235
public Mono<ApiFactory> callAPIDelete(String routeName) {
192236
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.delete", Map.of("routename", routeName)));
193237

238+
Request r = DataController.getInstance().createRequest(routeName, baseUrl);
239+
194240
record ResponseData(int statusCode, String body) {}
195241

196242
return webClient.delete()
@@ -202,6 +248,13 @@ record ResponseData(int statusCode, String body) {}
202248
.subscribeOn(Schedulers.boundedElastic())
203249
.doOnNext(responseData -> {
204250
connectLib.Logger().INFO(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "call.threadinuse", "thread", Thread.currentThread().getName()));
251+
252+
String newStatus = (responseData.statusCode() >= 200 && responseData.statusCode() < 300) ? "success" : "error";
253+
try {
254+
DataController.getInstance().updateRequestStatus(r.getId(), newStatus);
255+
} catch (Exception e) {
256+
connectLib.Logger().CRITICAL(connectLib.LangManager().getMessage(CategoriesType.APICLIENT_CLASS, "general.error", Map.of("method", "GET", "exception", e.getMessage())));
257+
}
205258
})
206259
.map(responseData -> {
207260
apiFactory.setStatusCode(responseData.statusCode());

src/main/java/fr/sandro642/github/hook/HookManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public ResourceType initHook(ResourceType resourceType) {
4747
return this.resourceType;
4848
}
4949

50+
/**
51+
* Returns the current resource type.
52+
*
53+
* @return the current resource type
54+
*/
55+
public ResourceType getResourceType() {
56+
return resourceType;
57+
}
58+
5059
/**
5160
* Sets the file location key based on the resource type.
5261
* This method updates the store with the file location key based on the resource type.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package fr.sandro642.github.spring;
2+
3+
import org.springframework.boot.Banner;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
import reactor.core.publisher.Mono;
7+
import reactor.core.scheduler.Schedulers;
8+
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
12+
/**
13+
* Main application class for starting the Spring Boot application.
14+
*/
15+
16+
@SpringBootApplication
17+
public class Application {
18+
19+
// Singleton instance
20+
private static Application instance;
21+
22+
/**
23+
* Starts the Spring Boot application in a non-blocking manner.
24+
* @return a Mono that completes when the application has started
25+
*/
26+
public Mono<Void> startApplication() {
27+
return Mono.fromRunnable(() -> {
28+
SpringApplication app = new SpringApplication(Application.class);
29+
app.setBannerMode(Banner.Mode.OFF); // supprime le banner Spring
30+
app.setLogStartupInfo(false); // désactive l'info de démarrage
31+
Map<String, Object> props = new HashMap<>();
32+
props.put("logging.level.root", "OFF"); // coupe l'affichage des logs
33+
app.setDefaultProperties(props);
34+
app.run();
35+
}).subscribeOn(Schedulers.boundedElastic()).then();
36+
}
37+
38+
/**
39+
* Gets the singleton instance of the Application class.
40+
* @return the singleton Application instance
41+
*/
42+
public static Application getInstance() {
43+
if (instance == null) {
44+
instance = new Application();
45+
}
46+
return instance;
47+
}
48+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package fr.sandro642.github.spring.controller;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.context.annotation.Primary;
6+
7+
/**
8+
* Configuration class for controller beans.
9+
*/
10+
11+
@Configuration
12+
public class ControllerConfig {
13+
14+
/**
15+
* Defines the primary DataController bean.
16+
* @return the singleton instance of DataController
17+
*/
18+
@Bean
19+
@Primary
20+
public DataController dataController() {
21+
return DataController.getInstance();
22+
}
23+
}

0 commit comments

Comments
 (0)