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}">&larr; 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 &copy; 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>