You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2019/08/10 07:50:07 UTC
[servicecomb-pack] 02/36: SCB-1411 Add UI Prototype
This is an automated email from the ASF dual-hosted git repository.
ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-pack.git
commit 20be1ab008c7ae07c7474dc6a6a03e7f1c0588f4
Author: Lei Zhang <co...@gmail.com>
AuthorDate: Tue Aug 6 09:54:32 2019 +0800
SCB-1411 Add UI Prototype
---
alpha/alpha-ui/README.md | 3 +
.../servicecomb/pack/alpha/ui/IndexController.java | 60 +++++++
.../pack/alpha/ui/TransactionController.java | 124 +++++++++++++++
.../pack/alpha/ui/UIAutoConfiguration.java | 29 ++++
.../pack/alpha/ui/vo/DataTablesRequestDTO.java | 70 +++++++++
.../pack/alpha/ui/vo/DataTablesResponseDTO.java | 88 +++++++++++
.../servicecomb/pack/alpha/ui/vo/EventDTO.java | 172 +++++++++++++++++++++
.../pack/alpha/ui/vo/SubTransactionDTO.java | 111 +++++++++++++
.../pack/alpha/ui/vo/TransactionRowDTO.java | 136 ++++++++++++++++
.../src/main/resources/META-INF/spring.factories | 17 ++
.../src/main/resources/static/css/alpha.css | 31 ++++
.../static/js/alpha-transaction-details.js | 30 ++++
.../main/resources/static/js/alpha-transaction.js | 95 ++++++++++++
.../src/main/resources/templates/error.html | 33 ++++
.../main/resources/templates/fragments/footer.html | 24 +++
.../main/resources/templates/fragments/header.html | 91 +++++++++++
.../resources/templates/fragments/main_layout.html | 90 +++++++++++
.../resources/templates/fragments/sidebar.html | 63 ++++++++
.../templates/fragments/transaction_table.html | 35 +++++
.../src/main/resources/templates/index.html | 133 ++++++++++++++++
.../src/main/resources/templates/saga.html | 40 +++++
.../src/main/resources/templates/search.html | 40 +++++
.../alpha-ui/src/main/resources/templates/tcc.html | 40 +++++
.../resources/templates/transaction_details.html | 102 ++++++++++++
24 files changed, 1657 insertions(+)
diff --git a/alpha/alpha-ui/README.md b/alpha/alpha-ui/README.md
new file mode 100644
index 0000000..5bbf087
--- /dev/null
+++ b/alpha/alpha-ui/README.md
@@ -0,0 +1,3 @@
+# ALPHA UI
+
+http://localhost:8090/admin
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/IndexController.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/IndexController.java
new file mode 100644
index 0000000..d293711
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/IndexController.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui;
+
+import org.springframework.boot.web.servlet.error.ErrorController;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+public class IndexController implements ErrorController {
+
+ // index
+ @GetMapping("/admin")
+ public String index() {
+ return "index";
+ }
+
+ @GetMapping("/ui/saga")
+ public String sagaIndex() {
+ return "saga";
+ }
+
+ @GetMapping("/ui/tcc")
+ public String tccIndex() {
+ return "tcc";
+ }
+
+ @GetMapping("/ui/search")
+ public String searchIndex(ModelMap map, @RequestParam(name = "q") String q) {
+ map.put("q", q);
+ return "search";
+ }
+
+ @GetMapping("/error")
+ public String handleError() {
+ return "error";
+ }
+
+ @Override
+ public String getErrorPath() {
+ return "/error";
+ }
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java
new file mode 100644
index 0000000..79be53c
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+import javax.websocket.server.PathParam;
+import org.apache.servicecomb.pack.alpha.ui.vo.DataTablesRequestDTO;
+import org.apache.servicecomb.pack.alpha.ui.vo.DataTablesResponseDTO;
+import org.apache.servicecomb.pack.alpha.ui.vo.EventDTO;
+import org.apache.servicecomb.pack.alpha.ui.vo.SubTransactionDTO;
+import org.apache.servicecomb.pack.alpha.ui.vo.TransactionRowDTO;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class TransactionController {
+
+ @PostMapping("/ui/transaction/sagalist")
+ @ResponseBody
+ public DataTablesResponseDTO sagaList(@ModelAttribute DataTablesRequestDTO dataTablesRequestDTO) {
+ List<TransactionRowDTO> data = new ArrayList<>();
+ for (int i = 0; i < dataTablesRequestDTO.getLength()-2; i++) {
+ data.add(TransactionRowDTO.builder().serviceName("Booking").instanceId("booking-1")
+ .globalTxId("xxxx-xxx-xxx").state("COMMITTED").beginTime(new Date()).endTime(new Date())
+ .subTxSize(3).durationTime(109).build());
+ }
+ for (int i = 0; i < 1; i++) {
+ data.add(TransactionRowDTO.builder().serviceName("Booking").instanceId("booking-1")
+ .globalTxId("xxxx-xxx-xxx").state("SUSPENDED").beginTime(new Date()).endTime(new Date())
+ .subTxSize(3).durationTime(109).build());
+ }
+ for (int i = 0; i < 1; i++) {
+ data.add(TransactionRowDTO.builder().serviceName("Booking").instanceId("booking-1")
+ .globalTxId("xxxx-xxx-xxx").state("COMPENSATED").beginTime(new Date()).endTime(new Date())
+ .subTxSize(3).durationTime(109).build());
+ }
+ return DataTablesResponseDTO.builder()
+ .draw(dataTablesRequestDTO.getDraw())
+ .recordsTotal(100)
+ .recordsFiltered(100)
+ .data(data)
+ .build();
+ }
+
+ @PostMapping("/ui/transaction/tcclist")
+ @ResponseBody
+ public DataTablesResponseDTO tccList(@ModelAttribute DataTablesRequestDTO dataTablesRequestDTO) {
+ List<TransactionRowDTO> data = new ArrayList<>();
+ return DataTablesResponseDTO.builder()
+ .draw(dataTablesRequestDTO.getDraw())
+ .recordsTotal(0)
+ .recordsFiltered(0)
+ .data(data)
+ .build();
+ }
+
+ @PostMapping("/ui/transaction/search")
+ @ResponseBody
+ public DataTablesResponseDTO searchList(@ModelAttribute DataTablesRequestDTO dataTablesRequestDTO) {
+ List<TransactionRowDTO> data = new ArrayList<>();
+ data.add(TransactionRowDTO.builder().serviceName("Booking").instanceId("booking-1")
+ .globalTxId("xxxx-xxx-xxx").state("SUSPENDED").beginTime(new Date()).endTime(new Date())
+ .subTxSize(3).durationTime(109).build());
+ return DataTablesResponseDTO.builder()
+ .draw(dataTablesRequestDTO.getDraw())
+ .recordsTotal(1)
+ .recordsFiltered(1)
+ .data(data)
+ .build();
+ }
+
+ @GetMapping("/ui/transaction/{globalTxId}")
+ public String searchList(ModelMap map, @PathParam("globalTxId") String globalTxId) {
+ List<EventDTO> events = new ArrayList<>();
+ List<SubTransactionDTO> subTransactions = new ArrayList<>();
+
+ globalTxId = UUID.randomUUID().toString();
+ String localTxId_1 = UUID.randomUUID().toString();
+ String localTxId_2 = UUID.randomUUID().toString();
+ String localTxId_3 = UUID.randomUUID().toString();
+ events.add(EventDTO.builder().type("SagaStartedEvent").serviceName("Booking").globalTxId(globalTxId).instanceId("booking-1").createTime(new Date()).localTxId(globalTxId).parentTxId(globalTxId).timeout(60000).build());
+ events.add(EventDTO.builder().type("TxStartedEvent").serviceName("Car").globalTxId(globalTxId).instanceId("car-1").createTime(new Date()).localTxId(localTxId_1).parentTxId(globalTxId).retries(3).compensationMethod("org.servicecomb.sample.car.CarService.cannelOrder()").build());
+ events.add(EventDTO.builder().type("TxEndedEvent").serviceName("Car").globalTxId(globalTxId).instanceId("car-1").createTime(new Date()).localTxId(localTxId_1).parentTxId(globalTxId).build());
+ events.add(EventDTO.builder().type("TxStartedEvent").serviceName("Hotel").globalTxId(globalTxId).instanceId("hotel-1").createTime(new Date()).localTxId(localTxId_2).parentTxId(globalTxId).retries(3).compensationMethod("org.servicecomb.sample.hotel.HotelService.cannelOrder()").build());
+ events.add(EventDTO.builder().type("TxEndedEvent").serviceName("Hotel").globalTxId(globalTxId).instanceId("hotel-1").createTime(new Date()).localTxId(localTxId_2).parentTxId(globalTxId).build());
+ events.add(EventDTO.builder().type("TxStartedEvent").serviceName("Flight").globalTxId(globalTxId).instanceId("flight-1").createTime(new Date()).localTxId(localTxId_3).parentTxId(globalTxId).retries(2).compensationMethod("org.servicecomb.sample.flight.FlightService.cannelOrder()").build());
+ events.add(EventDTO.builder().type("TxEndedEvent").serviceName("Flight").globalTxId(globalTxId).instanceId("flight-1").createTime(new Date()).localTxId(localTxId_3).parentTxId(globalTxId).build());
+ events.add(EventDTO.builder().type("TxAbortedEvent").serviceName("Flight").globalTxId(globalTxId).instanceId("flight-1").createTime(new Date()).localTxId(localTxId_3).parentTxId(globalTxId).exception("java.lang.NullPointerException\n"
+ + "at TestCompile.work(TestCompile.java:25)\n"
+ + "at TestCompile.main(TestCompile.java:17)").build());
+ events.add(EventDTO.builder().type("SagaEndedEvent").serviceName("Booking").globalTxId(globalTxId).instanceId("booking-1").createTime(new Date()).localTxId(globalTxId).parentTxId(globalTxId).build());
+
+ subTransactions.add(SubTransactionDTO.builder().parentTxId(globalTxId).localTxId(localTxId_1).beginTime(new Date()).endTime(new Date()).durationTime(10).state("COMMITTED").build());
+ subTransactions.add(SubTransactionDTO.builder().parentTxId(globalTxId).localTxId(localTxId_2).beginTime(new Date()).endTime(new Date()).durationTime(10).state("COMMITTED").build());
+ subTransactions.add(SubTransactionDTO.builder().parentTxId(globalTxId).localTxId(localTxId_3).beginTime(new Date()).endTime(new Date()).durationTime(10).state("COMMITTED").build());
+ map.put("events",events);
+ map.put("globalTxId",globalTxId);
+ map.put("subTransactions",subTransactions);
+ return "transaction_details";
+ }
+
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/UIAutoConfiguration.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/UIAutoConfiguration.java
new file mode 100644
index 0000000..b385762
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/UIAutoConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration
+@ConditionalOnProperty(value = {"alpha.feature.akka.enabled"})
+@Import({IndexController.class,TransactionController.class})
+public class UIAutoConfiguration {
+
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesRequestDTO.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesRequestDTO.java
new file mode 100644
index 0000000..5f7c7d9
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesRequestDTO.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui.vo;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class DataTablesRequestDTO {
+
+ private int draw;
+ private List<HashMap<String, String>> columns;
+ private List<HashMap<String, String>> order;
+ private int start;
+ private int length;
+
+ public int getDraw() {
+ return draw;
+ }
+
+ public void setDraw(int draw) {
+ this.draw = draw;
+ }
+
+ public List<HashMap<String, String>> getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List<HashMap<String, String>> columns) {
+ this.columns = columns;
+ }
+
+ public List<HashMap<String, String>> getOrder() {
+ return order;
+ }
+
+ public void setOrder(List<HashMap<String, String>> order) {
+ this.order = order;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesResponseDTO.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesResponseDTO.java
new file mode 100644
index 0000000..85d5629
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/DataTablesResponseDTO.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui.vo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DataTablesResponseDTO {
+ private int draw;
+ private int recordsTotal;
+ private int recordsFiltered;
+ private List<TransactionRowDTO> data = new ArrayList<>();
+
+ public int getDraw() {
+ return draw;
+ }
+
+ public int getRecordsTotal() {
+ return recordsTotal;
+ }
+
+ public int getRecordsFiltered() {
+ return recordsFiltered;
+ }
+
+ public List<TransactionRowDTO> getData() {
+ return data;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+
+ private int draw;
+ private int recordsTotal;
+ private int recordsFiltered;
+ private List<TransactionRowDTO> data = new ArrayList<>();
+
+ private Builder() {
+ }
+
+ public Builder draw(int draw) {
+ this.draw = draw;
+ return this;
+ }
+
+ public Builder recordsTotal(int recordsTotal) {
+ this.recordsTotal = recordsTotal;
+ return this;
+ }
+
+ public Builder recordsFiltered(int recordsFiltered) {
+ this.recordsFiltered = recordsFiltered;
+ return this;
+ }
+
+ public Builder data(List<TransactionRowDTO> data) {
+ this.data = data;
+ return this;
+ }
+
+ public DataTablesResponseDTO build() {
+ DataTablesResponseDTO dataTablesResponseDTO = new DataTablesResponseDTO();
+ dataTablesResponseDTO.recordsTotal = this.recordsTotal;
+ dataTablesResponseDTO.recordsFiltered = this.recordsFiltered;
+ dataTablesResponseDTO.draw = this.draw;
+ dataTablesResponseDTO.data = this.data;
+ return dataTablesResponseDTO;
+ }
+ }
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/EventDTO.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/EventDTO.java
new file mode 100644
index 0000000..fb5738f
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/EventDTO.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui.vo;
+
+import java.util.Date;
+
+public class EventDTO {
+ private String type;
+ private String globalTxId;
+ private String serviceName;
+ private String instanceId;
+ private String parentTxId;
+ private String localTxId;
+ private Date createTime;
+ private long timeout;
+ private long retries;
+ private String compensationMethod;
+ private String exception;
+
+ public String getType() {
+ return type;
+ }
+
+ public String getGlobalTxId() {
+ return globalTxId;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ public String getParentTxId() {
+ return parentTxId;
+ }
+
+ public String getLocalTxId() {
+ return localTxId;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public long getTimeout() {
+ return timeout;
+ }
+
+ public long getRetries() {
+ return retries;
+ }
+
+ public String getCompensationMethod() {
+ return compensationMethod;
+ }
+
+ public String getException() {
+ return exception;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+
+ public static final class Builder {
+
+ private String type;
+ private String globalTxId;
+ private String serviceName;
+ private String instanceId;
+ private String parentTxId;
+ private String localTxId;
+ private Date createTime;
+ private long timeout;
+ private long retries;
+ private String compensationMethod;
+ private String exception;
+
+ private Builder() {
+ }
+
+ public Builder type(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder globalTxId(String globalTxId) {
+ this.globalTxId = globalTxId;
+ return this;
+ }
+
+ public Builder serviceName(String serviceName) {
+ this.serviceName = serviceName;
+ return this;
+ }
+
+ public Builder instanceId(String instanceId) {
+ this.instanceId = instanceId;
+ return this;
+ }
+
+ public Builder parentTxId(String parentTxId) {
+ this.parentTxId = parentTxId;
+ return this;
+ }
+
+ public Builder localTxId(String localTxId) {
+ this.localTxId = localTxId;
+ return this;
+ }
+
+ public Builder createTime(Date createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public Builder timeout(long timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ public Builder retries(long retries) {
+ this.retries = retries;
+ return this;
+ }
+
+ public Builder compensationMethod(String compensationMethod) {
+ this.compensationMethod = compensationMethod;
+ return this;
+ }
+
+ public Builder exception(String exception) {
+ this.exception = exception;
+ return this;
+ }
+
+ public EventDTO build() {
+ EventDTO eventDTO = new EventDTO();
+ eventDTO.parentTxId = this.parentTxId;
+ eventDTO.serviceName = this.serviceName;
+ eventDTO.createTime = this.createTime;
+ eventDTO.type = this.type;
+ eventDTO.localTxId = this.localTxId;
+ eventDTO.instanceId = this.instanceId;
+ eventDTO.globalTxId = this.globalTxId;
+ eventDTO.timeout = this.timeout;
+ eventDTO.retries = this.retries;
+ eventDTO.compensationMethod = this.compensationMethod;
+ eventDTO.exception = this.exception;
+ return eventDTO;
+ }
+ }
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/SubTransactionDTO.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/SubTransactionDTO.java
new file mode 100644
index 0000000..12ea400
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/SubTransactionDTO.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui.vo;
+
+import java.util.Date;
+
+public class SubTransactionDTO {
+ private String localTxId;
+ private String parentTxId;
+ private Date beginTime;
+ private Date endTime;
+ private String state;
+ private long durationTime;
+
+ public String getLocalTxId() {
+ return localTxId;
+ }
+
+ public String getParentTxId() {
+ return parentTxId;
+ }
+
+ public Date getBeginTime() {
+ return beginTime;
+ }
+
+ public Date getEndTime() {
+ return endTime;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public long getDurationTime() {
+ return durationTime;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+
+ private String localTxId;
+ private String parentTxId;
+ private Date beginTime;
+ private Date endTime;
+ private String state;
+ private long durationTime;
+
+ private Builder() {
+ }
+
+ public Builder localTxId(String localTxId) {
+ this.localTxId = localTxId;
+ return this;
+ }
+
+ public Builder parentTxId(String parentTxId) {
+ this.parentTxId = parentTxId;
+ return this;
+ }
+
+ public Builder beginTime(Date beginTime) {
+ this.beginTime = beginTime;
+ return this;
+ }
+
+ public Builder endTime(Date endTime) {
+ this.endTime = endTime;
+ return this;
+ }
+
+ public Builder state(String state) {
+ this.state = state;
+ return this;
+ }
+
+ public Builder durationTime(long durationTime) {
+ this.durationTime = durationTime;
+ return this;
+ }
+
+ public SubTransactionDTO build() {
+ SubTransactionDTO subTransactionDTO = new SubTransactionDTO();
+ subTransactionDTO.localTxId = this.localTxId;
+ subTransactionDTO.state = this.state;
+ subTransactionDTO.durationTime = this.durationTime;
+ subTransactionDTO.beginTime = this.beginTime;
+ subTransactionDTO.endTime = this.endTime;
+ subTransactionDTO.parentTxId = this.parentTxId;
+ return subTransactionDTO;
+ }
+ }
+}
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionRowDTO.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionRowDTO.java
new file mode 100644
index 0000000..347838d
--- /dev/null
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionRowDTO.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.pack.alpha.ui.vo;
+
+import java.util.Date;
+
+public class TransactionRowDTO {
+
+ private String globalTxId;
+ private String serviceName;
+ private String instanceId;
+ private Date beginTime;
+ private Date endTime;
+ private String state;
+ private int subTxSize;
+ private long durationTime;
+
+ public String getGlobalTxId() {
+ return globalTxId;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ public Date getBeginTime() {
+ return beginTime;
+ }
+
+ public Date getEndTime() {
+ return endTime;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public int getSubTxSize() {
+ return subTxSize;
+ }
+
+ public long getDurationTime() {
+ return durationTime;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+
+ private String globalTxId;
+ private String serviceName;
+ private String instanceId;
+ private Date beginTime;
+ private Date endTime;
+ private String state;
+ private int subTxSize;
+ private long durationTime;
+
+ private Builder() {
+ }
+
+ public Builder globalTxId(String globalTxId) {
+ this.globalTxId = globalTxId;
+ return this;
+ }
+
+ public Builder serviceName(String serviceName) {
+ this.serviceName = serviceName;
+ return this;
+ }
+
+ public Builder instanceId(String instanceId) {
+ this.instanceId = instanceId;
+ return this;
+ }
+
+ public Builder beginTime(Date beginTime) {
+ this.beginTime = beginTime;
+ return this;
+ }
+
+ public Builder endTime(Date endTime) {
+ this.endTime = endTime;
+ return this;
+ }
+
+ public Builder state(String state) {
+ this.state = state;
+ return this;
+ }
+
+ public Builder subTxSize(int subTxSize) {
+ this.subTxSize = subTxSize;
+ return this;
+ }
+
+ public Builder durationTime(long durationTime) {
+ this.durationTime = durationTime;
+ return this;
+ }
+
+ public TransactionRowDTO build() {
+ TransactionRowDTO transactionRowDTO = new TransactionRowDTO();
+ transactionRowDTO.state = this.state;
+ transactionRowDTO.instanceId = this.instanceId;
+ transactionRowDTO.endTime = this.endTime;
+ transactionRowDTO.subTxSize = this.subTxSize;
+ transactionRowDTO.durationTime = this.durationTime;
+ transactionRowDTO.globalTxId = this.globalTxId;
+ transactionRowDTO.serviceName = this.serviceName;
+ transactionRowDTO.beginTime = this.beginTime;
+ return transactionRowDTO;
+ }
+ }
+}
diff --git a/alpha/alpha-ui/src/main/resources/META-INF/spring.factories b/alpha/alpha-ui/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..5521ef6
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.apache.servicecomb.pack.alpha.ui.UIAutoConfiguration
diff --git a/alpha/alpha-ui/src/main/resources/static/css/alpha.css b/alpha/alpha-ui/src/main/resources/static/css/alpha.css
new file mode 100644
index 0000000..004c9ce
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/static/css/alpha.css
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * DataTables style
+ */
+table.dataTable,
+div.dataTables_info,
+div.dataTables_length,
+div.dataTable_filter,
+div.dataTables_paginate {
+ font-size: .85rem
+}
+
+div.dataTables_paginate {
+ float: right
+}
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction-details.js b/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction-details.js
new file mode 100644
index 0000000..83fc79b
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction-details.js
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+$(document).ready(function () {
+ $('i[name="event_more"]').click(function (event) {
+ var more_id = '#'+$(event.target).attr("target")
+ if($(event.target).hasClass('fa-caret-square-down')){
+ $(event.target).removeClass("fa-caret-square-down")
+ $(event.target).addClass("fa-caret-square-up")
+ }else{
+ $(event.target).removeClass("fa-caret-square-up")
+ $(event.target).addClass("fa-caret-square-down")
+ }
+ $(more_id).toggleClass("d-none")
+ })
+});
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction.js b/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction.js
new file mode 100644
index 0000000..fb8ef44
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/static/js/alpha-transaction.js
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+$(document).ready(function () {
+
+ function datatablesRequest(data) {
+ for (var i = 0; i < data.columns.length; i++) {
+ column = data.columns[i];
+ column.searchRegex = column.search.regex;
+ column.searchValue = column.search.value;
+ delete(column.search);
+ }
+ }
+
+ var transaction_table = $('#dataTable').DataTable({
+ pagingType: "simple_numbers",
+ info: true,
+ filter: false,
+ lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
+ processing: true,
+ serverSide: true,
+ order: [[ 4, "desc" ]],
+ ajax: {
+ url : $('#transaction_config').attr('ajax'),
+ type: 'POST',
+ data: function(data) {
+ datatablesRequest(data);
+ }
+ },
+ language: {
+ lengthMenu: "_MENU_",
+ },
+ columns: [
+ { "data": "serviceName" },
+ { "data": "instanceId" },
+ { "data": "globalTxId" },
+ { "data": "subTxSize" },
+ { "data": "beginTime" },
+ { "data": "durationTime" },
+ { "data": "state" },
+ { "data": "" }
+ ],
+ columnDefs: [
+ {
+ render: function (data, type, row) {
+ return '<i class="fas fa-fw fa-bullseye row-transaction" style="cursor:pointer" globalTxId='+row.globalTxId+'></i>';
+ },
+ width: "50px",
+ targets: -1
+ },
+ {
+ render: function (data, type, row) {
+ if(data == 'COMMITTED'){
+ return '<span class="text-success">'+data+'</span>'
+ }else if(data == 'SUSPENDED'){
+ return '<span class="text-danger">'+data+'</span>'
+ }else if(data == 'COMPENSATED'){
+ return '<span class="text-warning">'+data+'</span>'
+ }else{
+ return data;
+ }
+ },
+ width: "50px",
+ targets: 6
+ },
+ { "visible": false, "targets": [ 4 ] }
+ ]
+ });
+
+ $('#dataTable tbody').on("click","tr", function(_event){
+ var data = transaction_table.row( this ).data();
+ window.location = "/ui/transaction/"+data.globalTxId
+ });
+
+ // table toolbar add state select & custom layout
+ $('#dataTable_wrapper .row:first div:first').removeClass("col-sm-12 col-md-6");
+ $('#dataTable_wrapper .row:first div:last').removeClass("col-sm-12 col-md-6");
+ $('#dataTable_wrapper .row:first div:first').addClass("col-sm-18 col-md-9");
+ $('#dataTable_wrapper .row:first div:last').addClass("col-sm-6 col-md-3");
+ $('#dataTable_wrapper .row:first div:last').append('<select name="state_select" class="custom-select custom-select-sm form-control form-control-sm"><option value="ALL">ALL</option><option value="COMMITTED">COMMITTED</option><option value="COMPENSATED">COMPENSATED</option><option value="SUSPENDED">SUSPENDED</option></select>')
+});
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/error.html b/alpha/alpha-ui/src/main/resources/templates/error.html
new file mode 100644
index 0000000..17422ae
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/error.html
@@ -0,0 +1,33 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml" layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Dashboard</title>
+</head>
+<body>
+<div layout:fragment="content" class="container-fluid">
+ <div class="text-center">
+ <div class="error mx-auto" data-text="404">404</div>
+ <p class="lead text-gray-800 mb-5">Page Not Found</p>
+ <p class="text-gray-500 mb-0">It looks like you found a glitch in the matrix...</p>
+ <a th:href="@{/admin}">← Back to Dashboard</a>
+ </div>
+</div>
+</body>
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/footer.html b/alpha/alpha-ui/src/main/resources/templates/fragments/footer.html
new file mode 100644
index 0000000..18a96ea
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/footer.html
@@ -0,0 +1,24 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<footer th:fragment="footer" class="sticky-footer" xmlns:th="http://www.w3.org/1999/xhtml">
+ <div class="container my-auto">
+ <div class="copyright text-center my-auto">
+ <span>Copyright © https://servicecomb.apache.org 2019</span>
+ </div>
+ </div>
+</footer>
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/header.html b/alpha/alpha-ui/src/main/resources/templates/fragments/header.html
new file mode 100644
index 0000000..4604926
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/header.html
@@ -0,0 +1,91 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Topbar -->
+<nav th:fragment="header" xmlns:th="http://www.w3.org/1999/xhtml" class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
+
+ <!-- Sidebar Toggle (Topbar) -->
+ <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
+ <i class="fa fa-bars"></i>
+ </button>
+
+ <!-- Topbar Search -->
+ <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search" action="/ui/search">
+ <div class="input-group">
+ <input type="text" name="q" class="form-control bg-light border-0 small" placeholder="Search for Global Transaction ID ..." aria-label="Search" aria-describedby="basic-addon2">
+ <div class="input-group-append">
+ <button class="btn btn-primary" type="button">
+ <i class="fas fa-search fa-sm"></i>
+ </button>
+ </div>
+ </div>
+ </form>
+
+ <!-- Topbar Navbar -->
+ <ul class="navbar-nav ml-auto">
+
+ <!-- Nav Item - Search Dropdown (Visible Only XS) -->
+ <li class="nav-item dropdown no-arrow d-sm-none">
+ <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <i class="fas fa-search fa-fw"></i>
+ </a>
+ <!-- Dropdown - Messages -->
+ <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
+ <form class="form-inline mr-auto w-100 navbar-search" action="/ui/search">
+ <div class="input-group">
+ <input type="text" name="q" class="form-control bg-light border-0 small" placeholder="Search for Global Transaction ID ..." aria-label="Search" aria-describedby="basic-addon2">
+ <div class="input-group-append">
+ <button class="btn btn-primary" type="button">
+ <i class="fas fa-search fa-sm"></i>
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </li>
+
+ <!-- Nav Item - Alerts -->
+ <li class="nav-item dropdown no-arrow mx-1">
+ <a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <i class="fas fa-bell fa-fw"></i>
+ <!-- Counter - Alerts -->
+ <span class="badge badge-danger badge-counter">1</span>
+ </a>
+ <!-- Dropdown - Alerts -->
+ <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown">
+ <h6 class="dropdown-header">
+ Alerts Center
+ </h6>
+ <a class="dropdown-item d-flex align-items-center" href="#">
+ <div class="mr-3">
+ <div class="icon-circle bg-primary">
+ <i class="fas fa-file-alt text-white"></i>
+ </div>
+ </div>
+ <div>
+ <div class="small text-gray-500">December 12, 2019</div>
+ <span class="font-weight-bold">Global transaction ID [205b2802-b4c9-11e9-a2a3-2a2ae2dbcce4] SUSPENDED</span>
+ </div>
+ </a>
+ <a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
+ </div>
+ </li>
+
+ </ul>
+
+</nav>
+<!-- End of Topbar -->
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html b/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html
new file mode 100644
index 0000000..467074e
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html
@@ -0,0 +1,90 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html lang="en" xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
+<head>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta name="description" content="">
+ <meta name="author" content="">
+
+ <title>Alpha Admin - Dashboard</title>
+ <link th:href="@{/webjars/font-awesome/css/all.min.css}" rel="stylesheet" type="text/css">
+ <link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet" type="text/css">
+ <link th:href="@{/css/sb-admin-2.min.css}" rel="stylesheet">
+ <link th:href="@{/css/alpha.css}" rel="stylesheet">
+
+</head>
+
+<body id="page-top">
+
+<!-- Page Wrapper -->
+<div id="wrapper">
+
+ <!-- Sidebar -->
+ <div th:replace="fragments/sidebar :: sidebar"></div>
+ <!-- End of Sidebar -->
+
+ <!-- Content Wrapper -->
+ <div id="content-wrapper" class="d-flex flex-column">
+
+ <!-- Main Content -->
+ <div id="content">
+
+ <!-- Topbar -->
+ <div th:replace="fragments/header :: header"></div>
+ <!-- End of Topbar -->
+
+ <!-- Page Content -->
+ <div layout:fragment="content" class="container-fluid"></div>
+ <!-- End of Page Content -->
+ </div>
+ <!-- End of Main Content -->
+
+ <!-- Footer -->
+ <div th:replace="fragments/footer :: footer"></div>
+ <!-- End of Footer -->
+
+ </div>
+ <!-- End of Content Wrapper -->
+
+</div>
+<!-- End of Page Wrapper -->
+
+<!-- Scroll to Top Button-->
+<a class="scroll-to-top rounded" href="#page-top">
+ <i class="fas fa-angle-up"></i>
+</a>
+
+<!-- Bootstrap core JavaScript-->
+<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
+<script th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
+<script th:src="@{/webjars/jquery-easing/jquery.easing.min.js}"></script>
+
+<!-- Custom scripts for all pages-->
+<script th:src="@{/js/sb-admin-2.min.js}"></script>
+
+<!-- Page scripts Content -->
+<div layout:fragment="scripts"></div>
+<!-- End of Page scripts Content -->
+
+</body>
+
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/sidebar.html b/alpha/alpha-ui/src/main/resources/templates/fragments/sidebar.html
new file mode 100644
index 0000000..89842c5
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/sidebar.html
@@ -0,0 +1,63 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Sidebar -->
+<ul th:fragment="sidebar" class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar" xmlns:th="http://www.w3.org/1999/xhtml">
+
+ <!-- Sidebar - Brand -->
+ <a class="sidebar-brand d-flex align-items-center justify-content-center" href="/admin">
+ <div class="sidebar-brand-icon rotate-n-15">
+ <i class="fas fa-laugh-wink"></i>
+ </div>
+ <div class="sidebar-brand-text mx-3">Alpha Admin</div>
+ </a>
+
+ <!-- Divider -->
+ <hr class="sidebar-divider my-0">
+
+ <!-- Nav Item - Dashboard -->
+ <li class="nav-item active">
+ <a class="nav-link" th:href="@{/admin}">
+ <i class="fas fa-fw fa-tachometer-alt"></i>
+ <span>Dashboard</span></a>
+ </li>
+
+ <!-- Divider -->
+ <hr class="sidebar-divider">
+
+ <li class="nav-item">
+ <a class="nav-link" th:href="@{/ui/saga}">
+ <i class="fas fa-fw fa-table"></i>
+ <span>SAGA</span></a>
+ </li>
+
+ <li class="nav-item">
+ <a class="nav-link" th:href="@{/ui/tcc}">
+ <i class="fas fa-fw fa-table"></i>
+ <span>TCC</span></a>
+ </li>
+
+ <!-- Divider -->
+ <hr class="sidebar-divider d-none d-md-block">
+
+ <!-- Sidebar Toggler (Sidebar) -->
+ <div class="text-center d-none d-md-inline">
+ <button class="rounded-circle border-0" id="sidebarToggle"></button>
+ </div>
+
+</ul>
+<!-- End of Sidebar -->
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/transaction_table.html b/alpha/alpha-ui/src/main/resources/templates/fragments/transaction_table.html
new file mode 100644
index 0000000..7455a35
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/transaction_table.html
@@ -0,0 +1,35 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<transaction_table th:fragment="transaction_table" class="sticky-footer bg-white" xmlns:th="http://www.w3.org/1999/xhtml">
+ <div class="table-responsive">
+ <table class="row-border table table-alpha" id="dataTable" width="100%" cellspacing="0">
+ <thead>
+ <tr>
+ <th>Service Name</th>
+ <th>Instance ID</th>
+ <th>Global Tx ID</th>
+ <th>Children</th>
+ <th>Created At</th>
+ <th>Duration(ms)</th>
+ <th>Final State</th>
+ <th style="width:50px;"></th>
+ </tr>
+ </thead>
+ </table>
+ </div>
+</transaction_table>
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/index.html b/alpha/alpha-ui/src/main/resources/templates/index.html
new file mode 100644
index 0000000..f79afde
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/index.html
@@ -0,0 +1,133 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Dashboard</title>
+</head>
+<body>
+ <div layout:fragment="content" class="container-fluid">
+ <!-- Page Heading -->
+ <h1 class="h3 mb-4 text-gray-800">Dashboard</h1>
+
+ <!-- Content Row -->
+ <div class="row">
+ <!-- Cluster Card -->
+ <div class="col-xl-3 col-md-6 mb-4">
+ <div class="card border-left-primary shadow h-100 py-2">
+ <div class="card-body">
+ <div class="row no-gutters align-items-center">
+ <div class="col mr-2">
+ <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Cluster</div>
+ <div class="h5 mb-0 font-weight-bold text-gray-800">2</div>
+ </div>
+ <div class="col-auto">
+ <i class="fas fa-calendar fa-2x text-gray-300"></i>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Total Transaction Card -->
+ <div class="col-xl-3 col-md-6 mb-4">
+ <div class="card border-left-primary shadow h-100 py-2">
+ <div class="card-body">
+ <div class="row no-gutters align-items-center">
+ <div class="col mr-2">
+ <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total Transaction</div>
+ <div class="h5 mb-0 font-weight-bold text-gray-800">215,00</div>
+ </div>
+ <div class="col-auto">
+ <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Successful Transaction Card -->
+ <div class="col-xl-3 col-md-6 mb-4">
+ <div class="card border-left-success shadow h-100 py-2">
+ <div class="card-body">
+ <div class="row no-gutters align-items-center">
+ <div class="col mr-2">
+ <div class="text-xs font-weight-bold text-success text-uppercase mb-1">Successful Transactions</div>
+ <div class="h5 mb-0 font-weight-bold text-gray-800">215,00</div>
+ </div>
+ <div class="col-auto">
+ <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Failed Transactions Card -->
+ <div class="col-xl-3 col-md-6 mb-4">
+ <div class="card border-left-danger shadow h-100 py-2">
+ <div class="card-body">
+ <div class="row no-gutters align-items-center">
+ <div class="col mr-2">
+ <div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Failed Transactions</div>
+ <div class="h5 mb-0 font-weight-bold text-gray-800">0</div>
+ </div>
+ <div class="col-auto">
+ <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Content Row -->
+ <div class="row">
+
+ <!-- Health Chart -->
+ <div class="col-xl-8 col-lg-7">
+ <div class="card shadow mb-4">
+ <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
+ <h6 class="m-0 font-weight-bold text-primary">Health Overview</h6>
+ </div>
+ <!-- Card Body -->
+ <div class="card-body">
+ <div class="chart-area">
+ <canvas></canvas>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Top Chart -->
+ <div class="col-xl-4 col-lg-5">
+ <div class="card shadow mb-4">
+ <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
+ <h6 class="m-0 font-weight-bold text-primary">Slow Transactions</h6>
+ </div>
+ <!-- Card Body -->
+ <div class="card-body">
+ <div class="chart-area">
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/saga.html b/alpha/alpha-ui/src/main/resources/templates/saga.html
new file mode 100644
index 0000000..540358f
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/saga.html
@@ -0,0 +1,40 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml"
+ layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Saga Transactions</title>
+</head>
+<body>
+<div layout:fragment="content" class="container-fluid">
+ <!-- Page Heading -->
+ <h1 class="h3 mb-4 text-gray-800">Saga Global Transaction </h1>
+ <!-- Transaction Table -->
+ <div id="transaction_config" ajax="/ui/transaction/sagalist">
+ <div th:replace="fragments/transaction_table :: transaction_table"></div>
+ </div>
+</div>
+
+<div layout:fragment="scripts">
+ <script th:src="@{/webjars/datatables/js/jquery.dataTables.min.js}"></script>
+ <script th:src="@{/webjars/datatables/js/dataTables.bootstrap4.min.js}"></script>
+ <script th:src="@{/js/alpha-transaction.js}"></script>
+</div>
+</body>
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/search.html b/alpha/alpha-ui/src/main/resources/templates/search.html
new file mode 100644
index 0000000..6a85394
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/search.html
@@ -0,0 +1,40 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml"
+ layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Tcc Transactions</title>
+</head>
+<body>
+<div layout:fragment="content" class="container-fluid">
+ <!-- Page Heading -->
+ <h1 class="h3 mb-4 text-gray-800" th:text="'Search [' + ${q} + '] Result'">Search Result Transaction </h1>
+ <!-- Transaction Table -->
+ <div id="transaction_config" ajax="/ui/transaction/search">
+ <div th:replace="fragments/transaction_table :: transaction_table"></div>
+ </div>
+</div>
+
+<div layout:fragment="scripts">
+ <script th:src="@{/webjars/datatables/js/jquery.dataTables.min.js}"></script>
+ <script th:src="@{/webjars/datatables/js/dataTables.bootstrap4.min.js}"></script>
+ <script th:src="@{/js/alpha-transaction.js}"></script>
+</div>
+</body>
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/tcc.html b/alpha/alpha-ui/src/main/resources/templates/tcc.html
new file mode 100644
index 0000000..5118bb3
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/tcc.html
@@ -0,0 +1,40 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml"
+ layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Tcc Transactions</title>
+</head>
+<body>
+<div layout:fragment="content" class="container-fluid">
+ <!-- Page Heading -->
+ <h1 class="h3 mb-4 text-gray-800">Tcc Global Transaction </h1>
+ <!-- Transaction Table -->
+ <div id="transaction_config" ajax="/ui/transaction/tcclist">
+ <div th:replace="fragments/transaction_table :: transaction_table"></div>
+ </div>
+</div>
+
+<div layout:fragment="scripts">
+ <script th:src="@{/webjars/datatables/js/jquery.dataTables.min.js}"></script>
+ <script th:src="@{/webjars/datatables/js/dataTables.bootstrap4.min.js}"></script>
+ <script th:src="@{/js/alpha-transaction.js}"></script>
+</div>
+</body>
+</html>
diff --git a/alpha/alpha-ui/src/main/resources/templates/transaction_details.html b/alpha/alpha-ui/src/main/resources/templates/transaction_details.html
new file mode 100644
index 0000000..ccac9aa
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/templates/transaction_details.html
@@ -0,0 +1,102 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml"
+ layout:decorate="~{fragments/main_layout}">
+<head>
+ <title>Alpha Admin - Transactions Details</title>
+</head>
+<body>
+<div layout:fragment="content" class="container-fluid">
+ <h1 class="h3 mb-4 text-gray-800" th:text="'Transaction [' + ${globalTxId} + '] Details'"></h1>
+ <div class="row">
+ <div class="col-xl-8 col-lg-7">
+ <div class="card shadow mb-4">
+ <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
+ <h6 class="m-0 font-weight-bold text-primary">Events</h6>
+ </div>
+ <div class="card-body">
+ <div class="events" th:each="event,stat : ${events}">
+ <div th:class="${event.type}=='TxAbortedEvent' ? 'row text-danger' : 'row'">
+ <div class="col-xl-6 col-lg-6">
+ <div><i class="fas fa-envelope"></i> <span th:class="${event.type}=='TxAbortedEvent' ? 'small text-danger' : 'small text-success'" th:text="${event.type}"></span></div>
+ <div><i class="fas fa-bell"></i> <span class="small" th:text="${event.serviceName} + '(' + ${event.instanceId} + ')'"></span></div>
+ <div><i class="fas fa-mars-stroke"></i> <span class="small" th:text="${event.parentTxId}"></span></div>
+ <div><i class="fas fa-transgender"></i> <span class="small" th:text="${event.localTxId}"></span></div>
+ </div>
+ <div class="col-xl-6 col-lg-6">
+ <div><i class="fas fa-calendar"></i> <span class="small" th:text="${event.createTime}"></span></div>
+ <div><i class="fas fa-clock"></i> <span class="small" th:text="${event.timeout}+' ms'"></span></div>
+ <div th:if="${event.type}==TxStartedEvent"><i class="fas fa-undo"></i> <span class="small" th:text="${event.retries}"></span></div>
+ <div th:if="${event.type}==TxStartedEvent or ${event.type}==TxAbortedEvent" class="position-absolute" style="bottom: 0px; right: 15px;">
+ <i name="event_more" class="fas fa-caret-square-down" style="cursor:pointer" th:target="'div-more-'+${stat.index}"></i>
+ </div>
+ </div>
+ </div>
+
+ <!-- TxStartedEvent more -->
+ <div th:id="'div-more-'+${stat.index}" th:if="${event.type}==TxStartedEvent" class="d-none" style="padding-top: 10px">
+ <div class="card border-primary">
+ <div class="card-header small border-primary bg-primary text-white">Compensation Method</div>
+ <div class="card-body">
+ <span class="small" th:text="${event.compensationMethod}"></span>
+ </div>
+ </div>
+ </div>
+
+ <!-- TxAbortedEvent more -->
+ <div th:id="'div-more-'+${stat.index}" th:if="${event.type}==TxAbortedEvent" class="d-none" style="padding-top: 10px">
+ <div class="card border-danger">
+ <div class="card-header small border-danger bg-danger text-white">Exception Stack</div>
+ <div class="card-body">
+ <span class="small" style="white-space: pre-line" th:text="${event.exception}"></span>
+ </div>
+ </div>
+ </div>
+ <hr th:if="${!stat.last}"/>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Top Chart -->
+ <div class="col-xl-4 col-lg-5">
+ <div class="card shadow mb-4">
+ <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
+ <h6 class="m-0 font-weight-bold text-primary">Sub Transactions</h6>
+ </div>
+ <!-- Card Body -->
+ <div class="card-body">
+ <div class="subTransactions" th:each="subTransaction, stat: ${subTransactions}">
+ <div><i class="fas fa-transgender"></i> <span class="small" th:text="${subTransaction.localTxId}"></span></div>
+ <div><i class="fas fa-calendar"></i> <span class="small" th:text="${subTransaction.beginTime}"></span></div>
+ <div><i class="fas fa-calendar"></i> <span class="small" th:text="${subTransaction.endTime}"></span></div>
+ <div><i class="fas fa-bullhorn"></i> <span class="small" th:text="${subTransaction.state}"></span></div>
+ <div><i class="fas fa-clock"></i> <span class="small" th:text="${subTransaction.durationTime}+' ms'"></span></div>
+ <hr th:if="${!stat.last}"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div layout:fragment="scripts">
+ <script th:src="@{/js/alpha-transaction-details.js}"></script>
+</div>
+</body>
+</html>