Odoo provides a wide range of field widgets to display different types of data in the user interface. However, there may be cases where you need to customize an existing field widget or create a new one to meet your specific needs. Example Let’s create a custom boolean field widget called boolean_badge. This widget will display a badge with the text “Yes” or “No,” depending on the value of the field. To create the widget, we first need to create a new JavaScript file in our module’s static/src/js directory. In this file, we will import the standardFieldProps object from the @web/views/fields/standard_field_props module. This object contains a set of standard props that are common to all field widgets. We will also import the Component class from the Owl library.import { registry } from “@web/core/registry”; import { standardFieldProps } from “@web/views/fields/standard_field_props”; const { Component } = owl;
Next, we need to define a new class called BooleanBadge that extends the Component class. This class will contain the logic for rendering the badge and handling user interactions.
In the setup() method, we are setting the default values for the trueValue, falseValue, trueColor, falseColor, and defaultColor props. We can also use the setup() method to initialize any other state that the widget needs.
The updateValue() method is called when the value of the field changes. This method updates the state of the widget and re-renders it.
Now that we have defined the widget class, we need to register it with Odoo. To do this, we add the following code to the end of the JavaScript file.BoolBadge.template = “BoolBadge” BoolBadge.props = standardFieldProps BoolBadge.supportedTypes = [“boolean”] registry.category(“fields”).add(“boolean_badge”,BoolBadge)
The template prop specifies the name of the template file that will be used to render the widget. The props prop specifies the props that are accepted by the widget. The supportedTypes prop specifies the types of fields that the widget can be used with.
Finally, we need to create the template file for the widget. Create a new file in the static/src/xml directory of your module called BooleanBadge.xml. In this file, add the following code:<?xml version=”1.0″ encoding=”UTF-8″ ?> <templates> <t t-name=”BooleanBadge” owl=”1″> <span class=”badge rounded-pill m-2 p-2 border” t-att-class=”props.value ? ‘text-white’ : ‘text-black’ t-esc=”trueValue” t-attf-style=”background-color: {{ props.value ? trueColor : defaultColor}}” t-on-click=”() => this.updateValue(true)”/> <span class=”badge rounded-pill m-2 p-2 border” t-att-class=”props.value ? ‘text-black’ : ‘text-white'” t-esc=”falseValue” t-attf-style=”background-color: {{ props.value ? defaultColor : falseColor}}” t-on-click=”() => this.updateValue(false)”/> </t> </templates>
This template will display a badge with the text “Yes” or “No” depending on the value of the field. The background color of the badge will be determined by the trueColor or falseColor prop, depending on the value of the field.
Once you have created the JavaScript and XML files for the widget, you can use them in your Odoo views. To add the widget to a field, simply add the following attribute to the field:widget=”boolean_badge”
Now, let’s add this widget to the test field inside the product template page.<?xml version=”1.0″ encoding=”UTF-8″ ?> <odoo> <record id=”product_template_only_form_view” model=”ir.ui.view”> <field name=”name”>product.template.inherit.coc</field> <field name=”model”>product.template</field> <field name=”inherit_id” ref=”product.product_template_only_form_view”/> <field name=”arch” type=”xml”> <field name=”detailed_type” position=”after”> <field name=”test_field” widget=”boolean_badge”/> </field> </field> </record> </odoo>
Now, the field looks like as follows
Extending the BooleanBadge widget to add options
You can extend the BooleanBadge widget to add options that allow you to customize the appearance of the badge and the text that is displayed. For example, you could add an option to change the size of the badge, the font of the badge text, or the border of the badge.
To extend the BooleanBadge widget to add options, you can create a new JavaScript file in the static/src/js directory of your module. Then, Import the BooleanBadge widget from your existing module. Define a new class that extends the BooleanBadge widget. Add a new prop to your widget to store the value of the option. Implement any custom behavior for your option, and register your new widget in the registry module.
To use the CustomBoolBadge widget, you can add it to a view in the same way that you would add any other field widget. For example, the following code would add a CustomBoolBadge widget to the test_field field:<?xml version=”1.0″ encoding=”UTF-8″ ?> <odoo> <record id=”product_template_only_form_view” model=”ir.ui.view”> <field name=”name”>product.template.inherit.coc</field> <field name=”model”>product.template</field> <field name=”inherit_id” ref=”product.product_template_only_form_view”/> <field name=”arch” type=”xml”> <field name=”detailed_type” position=”after”> <field name=”test_field” widget=”custom_bool_badge” options=”{‘trueColor’: ‘blue’, ‘trueValue’: ‘Yes’, ‘falseColor’: ‘yellow’, ‘falseValue’: ‘No’}”/> </field> </field> </record> </odoo>
In this, we have given trueColor as blue and falseColor as yellow and corresponding values. Let’s see the result.
Now we can see the color has changed to blue and yellow, respectively.
This is how we can extend and add features to the existing field widgets in Odoo 16.
On Windows, Docker runs in a VM called MobyLinuxVM, but you cannot login to that VM via Hyper-V Manager. We aren’t technically going to SSH into the VM, we’ll create a container that has full root access and then access the file system from there.
2022-12-14 09:01:38,994 32508 WARNING odoo odoo.modules.loading: The model estate.property has no access rules, consider adding one. E.g. access_estate_property,access_estate_property,model_estate_property,base.group_user,1,0,0,0
The perm_method have completely different semantics than for ir.model.access: for rules, they specify which operation the rules applies for. If an operation is not selected, then the rule is not checked for it, as if the rule did not exist.
perm_method的eval值不能同时为"False"、"0",否则会违反 ir_rule表的检查约束ir_rule_no_access_rights:CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)
ASP.NET Core projects are configured to bind to a random HTTP port between 5000-5300 and a random HTTPS port between 7000-7300. This default configuration is specified in the generated Properties/launchSettings.json file and can be overridden. If no ports are specified, Kestrel binds to:
http://localhost:5000
https://localhost:5001 (when a local development certificate is present)
The value provided using these approaches can be one or more HTTP and HTTPS endpoints (HTTPS if a default cert is available). Configure the value as a semicolon-separated list (for example, "Urls": "http://localhost:8000;http://localhost:8001").
The development certificate is available only for the user that generates the certificate. Some browsers require granting explicit permission to trust the local development certificate.
UseUrls, the --urls command-line argument, urls host configuration key, and the ASPNETCORE_URLS environment variable also work but have the limitations noted later in this section (a default certificate must be available for HTTPS endpoint configuration).
KestrelServerOptions configuration:
ConfigureEndpointDefaults(Action<ListenOptions>)
Specifies a configuration Action to run for each specified endpoint. Calling ConfigureEndpointDefaults multiple times replaces prior Actions with the last Action specified:
Enables Kestrel to load endpoints from an IConfiguration. The configuration must be scoped to the configuration section for Kestrel. The Configure(IConfiguration, bool) overload can be used to enable reloading endpoints when the configuration source changes.
By default, Kestrel configuration is loaded from the Kestrel section and reloading changes is enabled:
Specifies a configuration Action to run for each HTTPS endpoint. Calling ConfigureHttpsDefaults multiple times replaces prior Actions with the last Action specified.
filename is the path and file name of a certificate file, relative to the directory that contains the app’s content files.
password is the password required to access the X.509 certificate data.
configureOptions is an Action to configure the HttpsConnectionAdapterOptions. Returns the ListenOptions.
storeName is the certificate store from which to load the certificate.
subject is the subject name for the certificate.
allowInvalid indicates if invalid certificates should be considered, such as self-signed certificates.
location is the store location to load the certificate from.
serverCertificate is the X.509 certificate.
In production, HTTPS must be explicitly configured. At a minimum, a default certificate must be provided.
Supported configurations described next:
No configuration
Replace the default certificate from configuration
Change the defaults in code
No configuration
Kestrel listens on http://localhost:5000 and https://localhost:5001 (if a default cert is available).
Replace the default certificate from configuration
A default HTTPS app settings configuration schema is available for Kestrel. Configure multiple endpoints, including the URLs and the certificates to use, either from a file on disk or from a certificate store.
In the following appsettings.json example:
Set AllowInvalid to true to permit the use of invalid certificates (for example, self-signed certificates).
Any HTTPS endpoint that doesn’t specify a certificate (HttpsDefaultCert in the example that follows) falls back to the cert defined under Certificates:Default or the development certificate.
In the preceding example, certificate passwords are stored in plain-text in appsettings.json. The $CREDENTIAL_PLACEHOLDER$ token is used as a placeholder for each certificate’s password. To store certificate passwords securely in development environments, see Protect secrets in development. To store certificate passwords securely in production environments, see Azure Key Vault configuration provider. Development secrets shouldn’t be used for production or test.
Schema notes:
Endpoints names are case-insensitive. For example, HTTPS and Https are equivalent.
The Url parameter is required for each endpoint. The format for this parameter is the same as the top-level Urls configuration parameter except that it’s limited to a single value.
These endpoints replace those defined in the top-level Urls configuration rather than adding to them. Endpoints defined in code via Listen are cumulative with the endpoints defined in the configuration section.
The Certificate section is optional. If the Certificate section isn’t specified, the defaults defined in Certificates:Default are used. If no defaults are available, the development certificate is used. If there are no defaults and the development certificate isn’t present, the server throws an exception and fails to start.
KestrelServerOptions.ConfigurationLoader can be directly accessed to continue iterating on the existing loader, such as the one provided by WebApplicationBuilder.WebHost.
The configuration section for each endpoint is available on the options in the Endpoint method so that custom settings may be read.
Multiple configurations may be loaded by calling Configure(IConfiguration) again with another section. Only the last configuration is used, unless Load is explicitly called on prior instances. The metapackage doesn’t call Load so that its default configuration section may be replaced.
KestrelConfigurationLoader mirrors the Listen family of APIs from KestrelServerOptions as Endpoint overloads, so code and config endpoints may be configured in the same place. These overloads don’t use names and only consume default settings from configuration.
Change the defaults in code
ConfigureEndpointDefaults and ConfigureHttpsDefaults can be used to change default settings for ListenOptions and HttpsConnectionAdapterOptions, including overriding the default certificate specified in the prior scenario. ConfigureEndpointDefaults and ConfigureHttpsDefaults should be called before any endpoints are configured.
Server Name Indication (SNI) can be used to host multiple domains on the same IP address and port. For SNI to function, the client sends the host name for the secure session to the server during the TLS handshake so that the server can provide the correct certificate. The client uses the furnished certificate for encrypted communication with the server during the secure session that follows the TLS handshake.
SNI can be configured in two ways:
Create an endpoint in code and select a certificate using the host name with the ServerCertificateSelector callback.
Configure a mapping between host names and HTTPS options in Configuration. For example, JSON in the appsettings.json file.
SNI with ServerCertificateSelector
Kestrel supports SNI via the ServerCertificateSelector callback. The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate:
C#Copy
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var subExampleCert = CertificateLoader.LoadFromStoreCert(
"sub.example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var certs = new Dictionary<string, X509Certificate2>(
StringComparer.OrdinalIgnoreCase)
{
["localhost"] = localhostCert,
["example.com"] = exampleCert,
["sub.example.com"] = subExampleCert
};
httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
{
if (name is not null && certs.TryGetValue(name, out var cert))
{
return cert;
}
return exampleCert;
};
});
});
});
SNI with ServerOptionsSelectionCallback
Kestrel supports additional dynamic TLS configuration via the ServerOptionsSelectionCallback callback. The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate and TLS configuration. Default certificates and ConfigureHttpsDefaults are not used with this callback.
C#Copy
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
{
if (string.Equals(clientHelloInfo.ServerName, "localhost",
StringComparison.OrdinalIgnoreCase))
{
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = localhostCert,
// Different TLS requirements for this host
ClientCertificateRequired = true
});
}
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = exampleCert
});
}, state: null!);
});
});
});
SNI with TlsHandshakeCallbackOptions
Kestrel supports additional dynamic TLS configuration via the TlsHandshakeCallbackOptions.OnConnection callback. The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate, TLS configuration, and other server options. Default certificates and ConfigureHttpsDefaults are not used with this callback.
C#Copy
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
listenOptions.UseHttps(new TlsHandshakeCallbackOptions
{
OnConnection = context =>
{
if (string.Equals(context.ClientHelloInfo.ServerName, "localhost",
StringComparison.OrdinalIgnoreCase))
{
// Different TLS requirements for this host
context.AllowDelayedClientCertificateNegotation = true;
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = localhostCert
});
}
return new ValueTask<SslServerAuthenticationOptions>(
new SslServerAuthenticationOptions
{
ServerCertificate = exampleCert
});
}
});
});
});
});
SNI in configuration
Kestrel supports SNI defined in configuration. An endpoint can be configured with an Sni object that contains a mapping between host names and HTTPS options. The connection host name is matched to the options and they are used for that connection.
The following configuration adds an endpoint named MySniEndpoint that uses SNI to select HTTPS options based on the host name:
JSONCopy
{
"Kestrel": {
"Endpoints": {
"MySniEndpoint": {
"Url": "https://*",
"SslProtocols": ["Tls11", "Tls12"],
"Sni": {
"a.example.org": {
"Protocols": "Http1AndHttp2",
"SslProtocols": ["Tls11", "Tls12", "Tls13"],
"Certificate": {
"Subject": "<subject; required>",
"Store": "<certificate store; required>",
},
"ClientCertificateMode" : "NoCertificate"
},
"*.example.org": {
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "$CREDENTIAL_PLACEHOLDER$"
}
},
"*": {
// At least one subproperty needs to exist per SNI section or it
// cannot be discovered via IConfiguration
"Protocols": "Http1",
}
}
}
},
"Certificates": {
"Default": {
"Path": "<path to .pfx file>",
"Password": "$CREDENTIAL_PLACEHOLDER$"
}
}
}
}
Warning
In the preceding example, certificate passwords are stored in plain-text in appsettings.json. The $CREDENTIAL_PLACEHOLDER$ token is used as a placeholder for each certificate’s password. To store certificate passwords securely in development environments, see Protect secrets in development. To store certificate passwords securely in production environments, see Azure Key Vault configuration provider. Development secrets shouldn’t be used for production or test.
Exact match. For example, a.example.org matches a.example.org.
Wildcard prefix. If there are multiple wildcard matches then the longest pattern is chosen. For example, *.example.org matches b.example.org and c.example.org.
Full wildcard. * matches everything else, including clients that aren’t using SNI and don’t send a host name.
The matched SNI configuration is applied to the endpoint for the connection, overriding values on the endpoint. If a connection doesn’t match a configured SNI host name then the connection is refused.
SNI requirements
All websites must run on the same Kestrel instance. Kestrel doesn’t support sharing an IP address and port across multiple instances without a reverse proxy.
SSL/TLS Protocols
SSL Protocols are protocols used for encrypting and decrypting traffic between two peers, traditionally a client and a server.
In the preceding example, the certificate password is stored in plain-text in appsettings.json. The $CREDENTIAL_PLACEHOLDER$ token is used as a placeholder for the certificate’s password. To store certificate passwords securely in development environments, see Protect secrets in development. To store certificate passwords securely in production environments, see Azure Key Vault configuration provider. Development secrets shouldn’t be used for production or test.
The default value, SslProtocols.None, causes Kestrel to use the operating system defaults to choose the best protocol. Unless you have a specific reason to select a protocol, use the default.
In the preceding example, the certificate password is stored in plain-text in appsettings.json. The $CREDENTIAL_PLACEHOLDER$ token is used as a placeholder for the certificate’s password. To store certificate passwords securely in development environments, see Protect secrets in development. To store certificate passwords securely in production environments, see Azure Key Vault configuration provider.
The default value is ClientCertificateMode.NoCertificate where Kestrel will not request or require a certificate from the client.
Call UseConnectionLogging to emit Debug level logs for byte-level communication on a connection. Connection logging is helpful for troubleshooting problems in low-level communication, such as during TLS encryption and behind proxies. If UseConnectionLogging is placed before UseHttps, encrypted traffic is logged. If UseConnectionLogging is placed after UseHttps, decrypted traffic is logged. This is built-in Connection Middleware.
On macOS, Linux, and Windows, certificates can be created using OpenSSL.
Bind to a Unix socket
Listen on a Unix socket with ListenUnixSocket for improved performance with Nginx, as shown in this example:
C#Copy
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
});
In the Nginx configuration file, set the server > location > proxy_pass entry to http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} is the name of the socket provided to ListenUnixSocket (for example, kestrel-test.sock in the preceding example).
Ensure that the socket is writeable by Nginx (for example, chmod go+w /tmp/kestrel-test.sock).
Port 0
When the port number 0 is specified, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel bound at runtime:
C#Copy
app.Run(async (context) =>
{
var serverAddressFeature = context.Features.Get<IServerAddressesFeature>();
if (serverAddressFeature is not null)
{
var listenAddresses = string.Join(", ", serverAddressFeature.Addresses);
// ...
}
});
Limitations
Configure endpoints with the following approaches:
These methods are useful for making code work with servers other than Kestrel. However, be aware of the following limitations:
HTTPS can’t be used with these approaches unless a default certificate is provided in the HTTPS endpoint configuration (for example, using KestrelServerOptions configuration or a configuration file as shown earlier in this article).
When both the Listen and UseUrls approaches are used simultaneously, the Listen endpoints override the UseUrls endpoints.
IIS endpoint configuration
When using IIS, the URL bindings for IIS override bindings are set by either Listen or UseUrls. For more information, see ASP.NET Core Module.
ListenOptions.Protocols
The Protocols property establishes the HTTP protocols (HttpProtocols) enabled on a connection endpoint or for the server. Assign a value to the Protocols property from the HttpProtocols enum.
HttpProtocols enum value
Connection protocol permitted
Http1
HTTP/1.1 only. Can be used with or without TLS.
Http2
HTTP/2 only. May be used without TLS only if the client supports a Prior Knowledge mode.
Http1AndHttp2
HTTP/1.1 and HTTP/2. HTTP/2 requires the client to select HTTP/2 in the TLS Application-Layer Protocol Negotiation (ALPN) handshake; otherwise, the connection defaults to HTTP/1.1.
The default ListenOptions.Protocols value for any endpoint is HttpProtocols.Http1AndHttp2.
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
listenOptions.Use((context, next) =>
{
var tlsFeature = context.Features.Get<ITlsHandshakeFeature>()!;
if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
{
throw new NotSupportedException(
$"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
}
return next();
});
});
});
Set the HTTP protocol from configuration
By default, Kestrel configuration is loaded from the Kestrel section. The following appsettings.json example establishes HTTP/1.1 as the default connection protocol for all endpoints:
Protocols specified in code override values set by configuration.
URL prefixes
When using UseUrls, --urls command-line argument, urls host configuration key, or ASPNETCORE_URLS environment variable, the URL prefixes can be in any of the following formats.
Only HTTP URL prefixes are valid. Kestrel doesn’t support HTTPS when configuring URL bindings using UseUrls.
IPv4 address with port numberCopyhttp://65.55.39.10:80/ 0.0.0.0 is a special case that binds to all IPv4 addresses.
IPv6 address with port numberCopyhttp://[0:0:0:0:0:ffff:4137:270a]:80/ [::] is the IPv6 equivalent of IPv4 0.0.0.0.
Host name with port numberCopyhttp://contoso.com:80/ http://*:80/ Host names, *, and +, aren’t special. Anything not recognized as a valid IP address or localhost binds to all IPv4 and IPv6 IPs. To bind different host names to different ASP.NET Core apps on the same port, use HTTP.sys or a reverse proxy server. Reverse proxy server examples include IIS, Nginx, or Apache. WarningHosting in a reverse proxy configuration requires host filtering.
Host localhost name with port number or loopback IP with port numberCopyhttp://localhost:5000/ http://127.0.0.1:5000/ http://[::1]:5000/ When localhost is specified, Kestrel attempts to bind to both IPv4 and IPv6 loopback interfaces. If the requested port is in use by another service on either loopback interface, Kestrel fails to start. If either loopback interface is unavailable for any other reason (most commonly because IPv6 isn’t supported), Kestrel logs a warning.
前端绘制图形无非就是 HTML + CSS、Canvas、Svg 三种方式,我们综合做了一下对比,列出了相应的优劣势:
在流程图的场景下,不需要渲染大量的节点(最多几千个元素),对于动画的诉求也不高。Svg 基于 DOM 的特性会更适合我们,一个是学习成本和开发成本更低,另一个是基于 DOM 可以做的拓展也更多。不过 Svg 标签内部并不支持插入其他比如 div 这种标签,所以在实现某些功能的时候,都需要结合其他 HTML 标签。
所以最终我们选择使用 HTML + Svg 来完成图的渲染,Svg 负责图形、线的部分,HTML 来实现文本、菜单、背景等图层。