如何在ovirt中使用GWT框架为页面新增组件

敌法师
• 阅读 850

如何在ovirt中使用GWT框架为页面新增组件

Ovirt中的GWT框架(GWTP)

参考 ovirt gwt 代码分析

如何要在GWT页面新增或者修改组件?

修改、新增、删除菜单可以参考文档 增加/修改左侧导航
  1. 定位页面

    ovirt中的页面明规则,ovirt页面
    以集群为例
    • 集群列表页面
      MainClusterView.java(V) 类似页面为 MainNetworkView.java MainHostView.java
    • tab页面
      SubTabClusterGeneralView.java 类似页面为SubTabHostGeneralView.java
    • 新建、删除、修改等各种按钮监听页面
      ClusterPopupView.java 类似页面为 HostPopupView.java

      要想找到这些页面可以通过该页面名称在PresenterModule.java页面中进行查询,PresenterModule 中定义了每个 tab、popubview 的 M、V、P 三者之间的关系。
  2. 修改页面
    定位页面后,可以对页面进行操作,比如新增、修改、隐藏某个组件。注意如果view页面有对应的xml页面,修改时需要将两个文件内容同步。
    以下以在新建、编辑虚拟网卡配置集页面中新增安全组下拉列表为例

    • 按照以上方法对页面进行定位,找到需要修改页面 VnicProfilePopupView.java
      且可以发现VnicProfilePopupView.java存在对应VnicProfilePopupView.ui.xml中存在各种引用
    • 在页面中新增安全组单选组件
    1. VnicProfilePopupView.ui.xml
      在VnicProfilePopupView.ui.xml中存在各种引用

       <ui:UiBinder
      <!-- GWT组件 提供可以引用的组件(GWT原生、GWTbootstrap3、ovirt原生)  -->
      xmlns:ui="urn:ui:com.google.gwt.uibinder"
      xmlns:g="urn:import:com.google.gwt.user.client.ui" 
      xmlns:d="urn:import:org.ovirt.engine.ui.common.widget.dialog"
      xmlns:e="urn:import:org.ovirt.engine.ui.common.widget.editor"
      xmlns:ge="urn:import:org.ovirt.engine.ui.common.widget.editor.generic"
      xmlns:k="urn:import:org.ovirt.engine.ui.common.widget.form.key_value"
      xmlns:b="urn:import:org.gwtbootstrap3.client.ui">
      <!-- 引用应用常量,一般设置组件名称 -->
      <ui:with field='constants' type='org.ovirt.engine.ui.webadmin.ApplicationConstants' />
      建议使用原生,及框架中的已知简单组件,可以在网上查询文档进行参考
       <b:Row>
        <e:ListModelListBoxEditor ui:field="securityGroupsEditor" label="{constants.safeGroup}" usePatternFly="true" labelColSize="SM_6" widgetColSize="SM_6" />
       </b:Row>

      <e />: 组件所在库
      ListModelListBoxEditor:组件名称
      ui:field="securityGroupsEditor": 该参数需要和view中保存相同
      label="{constants.safeGroup}" : 组件显示名称
      labelColSize="SM_6" widgetColSize="SM_6" : 组件样式
      还可以在xml中新增css样式

      <ui:style>
          .firstRow {
              padding-top: 15px;
          }
          .hide_ext {
              display: none;
          }
      </ui:style>
      <b:Row addStyleNames="{style.hide_ext}">
         <b:Column size="SM_12" >
            <g:Label text="{constants.customPropertiesVnicProfile}" />
        </b:Column>
      </b:Row>
      声明的css可以使用addStyleNames="{style.hide_ext}"添加到组件上
    2. VnicProfilePopupView.java
      增加名称为xml中ui:field值的参数,类型对应所使用的的组件

      @UiField(provided = true)
      @Path("securityGroups.selectedItem")
      public ListModelListBoxEditor<SecurityGroupForVnic> securityGroupsEditor;

      在构造方法中对组件进行初始化

      securityGroupsEditor = new ListModelListBoxEditor<>(new SecurityGroupForVnicRenderer(constants));
    3. VnicProfileModel.java NewVnicProfileModel.java EditVnicProfileModel.java
      NewVnicProfileModel、EditVnicProfileModel继承了VnicProfileModel,相同操作在VnicProfileModel中实现。

      • 相同操作
        声明对象,用来保存后台查到的值,以及名称需要对应view页面中@Path("securityGroups.selectedItem")securityGroups

        //过滤从后台查来的值,使其符合组件对应数据格式
        private ListModel<SecurityGroupForVnic> securityGroups;
        
         public ListModel<SecurityGroupForVnic> getSecurityGroups() {
         return securityGroups;
         }
        
         public void setSecurityGroups(ListModel<SecurityGroupForVnic> securityGroups) {
         this.securityGroups = securityGroups;
         }
         //用来存取后台查询的值
         List<ExtSecurityGroupForCreate> securitys;
        
         public List<ExtSecurityGroupForCreate> getSecuritys() {
         return securitys;
         }
        
         public void setSecuritys(List<ExtSecurityGroupForCreate> securitys) {
         this.securitys = securitys;
         }

        声明空选项,下拉列表设置空选项

        private static final SecurityGroupForVnic EMPTY_SECURITY = new SecurityGroupForVnic();

        在构造方法中对数据进行初始化

        // 初始化下拉列表值
        setSecurityGroups(new ListModel<SecurityGroupForVnic>());
        //请求后台,查询安全局数据
        querySecurityGroupList();

        Frontend.getInstance().runQuery(): 请求后台接口方法
        QueryType.GetAllSecurityGroup: 后台请求query, 后台实现为GetAllSecurityGroupQuery
        new SecurityGroupQueryParameter(0, null) : 查询参数
        new AsyncQuery<QueryReturnValue>(): 接口请求回调,在该方法中向securitys赋值

        public void querySecurityGroupList(){
         Frontend.getInstance().runQuery(QueryType.GetAllSecurityGroup,
         new SecurityGroupQueryParameter(0),
         new AsyncQuery<QueryReturnValue>(returnValue -> {
             if (returnValue != null) {
                 setSecuritys(returnValue.getReturnValue());
             }
         }));
        }

        在安全组改变事件中增加initSecurityGroups()

        getDataCenters().getSelectedItemChangedEvent().addListener((ev, sender, args) -> {
        if (getDataCenters().getSelectedItem() != null) {
         Version dcCompatibilityVersion = getDataCenters().getSelectedItem().getCompatibilityVersion();
         Guid currentDcId = getDataCenters().getSelectedItem().getId();
         initCustomPropertySheet(dcCompatibilityVersion);
         initNetworkQoSList(currentDcId);
         initNetworkFilterList(dcCompatibilityVersion);
         initNetworkList(currentDcId);
         //该方位为重新初始化安全组下拉列表值
         initSecurityGroups();
        }
         });

        该方法对安全组下拉列表进行值的初始化

        private void initSecurityGroups(){
         if (!getSecurityGroups().getIsAvailable()) {
        return;
         }
         querySecurityGroupList();
         if (getSecuritys() != null){
        List<SecurityGroupForVnic> securityGroupForVnics = new ArrayList<>();
        securityGroupForVnics.add(EMPTY_SECURITY);
        getSecuritys().stream()
             .filter(sg -> getDataCenters().getSelectedItem() != null && getDataCenters().getSelectedItem().getId().toString().equals(sg.getDataCenterId())).
             forEach(sg -> {
                 SecurityGroupForVnic securityGroupForVnic = new SecurityGroupForVnic();
                 securityGroupForVnic.setId(Guid.createGuidFromString(sg.getId()));
                 securityGroupForVnic.setName(sg.getName());
                 securityGroupForVnics.add(securityGroupForVnic);
             });
        getSecurityGroups().setItems(securityGroupForVnics);
        initSecurityGroupsValue();
         }
         }

        保存时页面参数封装,把当前选中的值放到保存参数中

        SecurityGroupForVnic selectedItem = getSecurityGroups().getSelectedItem();
        if (selectedItem != null && selectedItem.getId() != null
         && !selectedItem.getId().equals(Guid.Empty)){
        Map<String ,String> sgs = new HashMap<>();
        sgs.put("SecurityGroups", selectedItem.getId().toString()); //$NON-NLS-1$
        vnicProfile.setCustomProperties(sgs);
        }else {
        vnicProfile.setCustomProperties(null);
        }
      • 差异
        NewVnicProfileModel.java 中需要将当前下拉列表中的值选中空选项

         @Override
         protected void initSecurityGroupsValue() {
         // Do nothing
        getSecurityGroups().setSelectedItem(Linq.firstOrNull(getSecurityGroups().getItems(),
         new Linq.NamePredicate(null)));
         }

        EditVnicProfileModel.java 需要将已选中的值渲染到下拉列表中

         @Override
         protected void initSecurityGroupsValue() {
         if(getProfile().getCustomProperties() != null && getProfile().getCustomProperties().get("SecurityGroups") != null){
        getSecurityGroups().setSelectedItem(Linq.firstOrNull(getSecurityGroups().getItems(),
         new Linq.IdPredicate<>(Guid.createGuidFromString(getProfile().getCustomProperties().get("SecurityGroups")))));
         }
         }
  3. 注意点

    1. frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml

      ovirt中如果想用backend创建的实体类,需要在该文件中进行声明
      <include name="common/businessentities/network/securitygroups/ExtSecurityGroupForCreate.java"/>
      <include name="common/businessentities/network/securitygroups/ExtSecurityGroupRuleForCreate.java"/>
      <include name="common/businessentities/network/securitygroups/SecurityGroupForVnic.java"/>
      <include name="common/action/securitygroup/SecurityGroupQueryParameter.java" />

    总结

    该文档只说明前台新建GWT组件时,需要做的操作,具体页面、具体功能需要根据实际进行设计
点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
4年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Stella981 Stella981
4年前
RestyGWT简介
定义:RestyGWT是一个REST服务GWT生成器和JavaObjectJSON数据格式转换引擎。它能够生成基于JSON的异步Restful服务代理,提供易于使用的RESTAPI。RESTServicesRestyGWT的RestServices能够生成基于JSON的异步Restful服务,和GWT中的异步类似:p
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这