All checks were successful
Deploy Static Site / deploy (push) Successful in 6m6s
266 lines
29 KiB
HTML
266 lines
29 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<title>Guidelines for developing microservices for portable services</title>
|
||
<meta name="generator" content="Help+Manual" />
|
||
<meta name="keywords" content="" />
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="description" content="Service settings Initialization and operation of a microservice may require certain settings to be available. Sometimes a microservice needs to be adjusted to fit the needs of..." />
|
||
<meta name="picture" content="" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:title" content="Full documentation for BRIX365 platform. Low-code developer guide. User guide. Admin guide. Developer guide." />
|
||
<meta property="og:url" content="https://brix365.com/en/help" />
|
||
<meta property="og:image" content="" />
|
||
<link rel="icon" href="favicon.png" type="image/png" />
|
||
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||
<link rel="stylesheet" href="./jquery-ui.min.css" />
|
||
<link rel="stylesheet" href="default.css" />
|
||
<link rel="stylesheet" href="./search-yandex.css" />
|
||
<link rel="stylesheet" href="./article.css" />
|
||
<link rel="stylesheet" href="./glossary.css" />
|
||
<link rel="stylesheet" href="./theme.css" />
|
||
<script type="text/javascript" src="jquery.js"></script>
|
||
<script type="text/javascript" src="helpman_settings.js"></script>
|
||
<script type="text/javascript" src="helpman_topicinit.js"></script>
|
||
|
||
<script type="text/javascript" src="highlight.js"></script>
|
||
<script type="text/javascript">
|
||
$(document).ready(function(){highlight();});
|
||
</script>
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<script>!function(e,t,c,n,r,a,m){e.ym=e.ym||function(){(e.ym.a=e.ym.a||[]).push(arguments)},e.ym.l=1*new Date;for(var s=0;s<document.scripts.length;s++)if(document.scripts[s].src===n)return;a=t.createElement(c),m=t.getElementsByTagName(c)[0],a.async=1,a.src=n,m.parentNode.insertBefore(a,m)}(window,document,"script","https://mc.yandex.ru/metrika/tag.js"),ym(83179930,"init",{clickmap:!0,trackLinks:!0,accurateTrackBounce:!0,webvisor:!0})</script><noscript><div><img alt=""src=https://mc.yandex.ru/watch/83179930 style=position:absolute;left:-9999px></div></noscript>
|
||
|
||
<header class="header elma-365">
|
||
<div class="container">
|
||
<a class="header__logo" href="https://brix365.com/en/help">
|
||
<img src="./logo-en.svg" alt="header logo">
|
||
</a>
|
||
<!-- <div class="hero__search-form" id="search-panel">
|
||
<form class="search-form" onsubmit="ym(83180416,'reachGoal','poisk')">
|
||
<label class="search-form__label">
|
||
<span id="reset-search" class="search__icon"></span>
|
||
<input class="search-form__input" type="text">
|
||
</label>
|
||
<input class="search-form__submit" type="submit" value="Submit">
|
||
</form>
|
||
</div> -->
|
||
|
||
<div class="hero__search-form" id="search-panel"> <form class="search-form"> <label class="search-form__label"> <span id="reset-search" class="search__icon"></span> <input class="search-form__input" type="text"> </label> <input class="search-form__submit" type="submit" value="Submit"> </form> </div>
|
||
<div class="hero__search">
|
||
<a href="#" id="search-icon" class="hero__search-icon">
|
||
<img src="search-icon-white.svg" alt="search string">
|
||
</a>
|
||
<a href="#" id="side-menu-icon" class="hero__side-icon">
|
||
<img src="side_menu.svg" alt="side menu">
|
||
</a>
|
||
</div>
|
||
<div class="header__navi">
|
||
|
||
<ul class="header__list"><li><span class="solution-select"><span class="solution-select__selected"></span><svg width="7" height="4" viewBox="0 0 7 4" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L3.5 3.5L6 1" stroke="white" stroke-linecap="round" stroke-linejoin="round"/></svg><ul class="solution-select__list"><li><a class="project-link" href="https://brix365.com/en/help/platform/get-trial.html">Platform</a></li><li><a class="project-link" href="https://brix365.com/en/help/ecm/ecm-functions.html">ECM</a></li><li><a class="project-link" href="https://brix365.com/en/help/crm/crm_overview.html">CRM</a></li><li><a class="project-link" href="https://brix365.com/en/help/service/service-functions.html">Service</a></li><li><a class="project-link" href="https://brix365.com/en/help/projects/projects-functions.html">Projects</a></li><li><a class="project-link" href="https://brix365.com/en/help/business_solutions/-elma365-store.html">Business Solutions</a></li></ul></span></li><li><a href="https://api.brix365.com/en/" target="_blank">API</a></li><li><a href="https://tssdk.brix365.com/" target="_blank">SDK</a></li></ul>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</header>
|
||
|
||
|
||
|
||
|
||
<main class="main container">
|
||
|
||
<aside class="sidebar" id="sidebar">
|
||
<div class="sidebar__header">
|
||
<a class="header__logo" href="https://brix365.com/en/help">
|
||
<img src="./logo-light-en.svg">
|
||
</a>
|
||
<span class="sidebar__close elma-365-close" id="close"></span>
|
||
</div>
|
||
<div class="sidebar__wrapper" id="side-menu">
|
||
|
||
</div>
|
||
</aside>
|
||
|
||
<article class="article" id="article">
|
||
<div class="article-inner">
|
||
<div class="content">
|
||
<header class="article__header">
|
||
<div class="article__bread" style="display:flex; gap:10px;">
|
||
<span id="subcategory" class="search-res__item-category search-res__item-category_subcategory subcategory article__badge"></span>
|
||
|
||
<div class="topic__breadcrumbs">
|
||
<p><a href="solutions-building.html">Build solutions in BRIX</a> > <a href="portable-microservices.html">Portable services in modules</a> / Guidelines for developing microservices for portable services</p>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="topic__title"><h1 class="p_Heading1"><span class="f_Heading1">Guidelines for developing microservices for portable services</span></h1>
|
||
</div>
|
||
|
||
</header>
|
||
<section class="article__content">
|
||
<div class="scroll-top-inner">
|
||
<a href="#h1-article" class="scroll-top"></a>
|
||
</div>
|
||
<!-- Placeholder for topic body. -->
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Service settings</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Initialization and operation of a microservice may require certain settings to be available. Sometimes a microservice needs to be adjusted to fit the needs of the consumer. For example, it may need to be possible to set a connection string for a data source. For this purpose, the developer of the microservice should add an opportunity to retrieve its settings. The developer of the module can pass the values of environment variables into the container that is to be deployed. Data from them can be used for the configuration of the microservice.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Depending on the framework chosen for development, this can be either direct reading of values from the environment variables or configuring the microservice via a separate provider, for instance as in </span><span style="font-family: Inter; font-weight: bold;">.NET</span><span style="font-family: Inter;">.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">With this approach, the module developer can submit their data to the microservice or even give this opportunity to the end user.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Note that environment variables are set then the container is initialized, and the changes made by the end user in the module when working with it will not be applied.</span></p>
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Provided API</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Module developers can interact with the microservice by sending HTTP requests from scripts, for example, in processes or widgets. To make it possible, a web API has to be developed and implemented for the microservice. Read about the best approaches and tools for creating web APIs in the following articles:</span></p>
|
||
<ul style="list-style-type:disc">
|
||
<li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;"><a href="https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design" target="_blank" class="weblink">RESTful web API design</a>.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;"><a href="https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf" target="_blank" class="weblink">Web API Design</a>.</span></li></ul>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">The provided API has to be documented in order to make it easier to use in the future.</span></p>
|
||
<h3 class="p_Heading3"><a id="communication-between-services" class="hmanchor"></a><span class="f_Heading3">Communication between two portable services</span></h3>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">In BRIX On-Premises and SaaS Enterprise editions, you can configure the interaction between two microservices within a single module using environment variables.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">To do this:</span></p>
|
||
<ol style="list-style-type:upper-roman">
|
||
<li value="1" style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;">Add an environment variable for service 1 to store the address of service 2. To do this, open the module, go to the editing page of the portable service and create the variable in the <span style="color: #0563c1;"><a href="portable-services.html#main-tab" class="topiclink">Docker container settings</a></span>.</li></ol>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 34px;">Let’s say that an environment variable with the service address 2 can be named <code><b>serv2url</b></code>. If the unique name of service 2 is <code><b>serv2</b></code>, then <code><b>{$_srv_serv2}</b></code> should be written as the value of the variable.</p>
|
||
<ol style="list-style-type:upper-roman">
|
||
<li value="2" style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;">After that, in portable service 1, you can get the URL of service 2 using the variable:</li></ol>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">serv2url, exists := os.LookupEnv("serv2Url")</span></p>
|
||
<ol style="list-style-type:upper-roman" start="3">
|
||
<li value="3" style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;">Using the received address, you can send an HTTP request:</span></li></ol>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">resp, err := http.Get(serv2url + "/hello")</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">This feature should be documented so that it can be used when working with the module.</span></p>
|
||
<h3 class="p_Heading3"><span class="f_Heading3">Ports</span></h3>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">By default, a portable service is configured to use port 3000. If the microservice uses a different port, this should be specified in the module’s documentation.</span></p>
|
||
<h3 class="p_Heading3"><span class="f_Heading3">Microservice state</span></h3>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">At the moment, storing the state of microservices is not supported in portable services. This means that when a microservice stops, data from it will be lost.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">That’s why you shouldn’t use the file system to store microservice data permanently.</span></p>
|
||
<h4 class="p_Heading4"><span class="f_Heading4">Example:</span></h4>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">You cannot: permanently store image files on the disk to access them upon users’ requests.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">You can: temporarily upload image files to the disk to process them instantly and send them back to the user.</span></p>
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Logs</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">When you develop your microservice, note that at the moment users cannot view logs in the file system or console. If you need to add logs, return them either using a separately developed API or send them to an external system that users will have access to.</span></p>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">начало внимание</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Note that the microservice does not save its state, so logs stored in files will be lost when the service is shut down.</span></p>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">конец внимание</span></p>
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Example with Go</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">The standard output for Go is the </span><code><b>os.Stdout</b></code><span style="font-family: Inter; font-weight: bold;"> </span><span style="font-family: Inter;">object that is practically a console. In the simplest case you can display data in this object by importing the </span><code><b>log</b></code><span style="font-family: Inter;"> module:</span></p>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">log.Print("Hello log")</span><br />
|
||
<span class="f_CodeExample">log.Printf("Hello log - %s", "hi yourself")</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Moreover, you can use specialized logging libraries that have rich functionality, including log levels.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">One example of such libraries is <a href="https://github.com/uber-go/zap" target="_blank" class="weblink">zap</a>. Below you can see an example of logs showed in a format that corresponds to </span><span style="font-family: Inter; font-weight: bold;">.e365</span><span style="font-family: Inter;">:</span></p>
|
||
<p class="p_CodeExample" style="page-break-inside: avoid;"><span class="f_CodeExample">// Initialization</span><br />
|
||
<span class="f_CodeExample">{</span><br />
|
||
<span class="f_CodeExample">enc := zap.NewProductionEncoderConfig()</span><br />
|
||
<span class="f_CodeExample">enc.TimeKey = "timestamp"</span><br />
|
||
<span class="f_CodeExample">enc.EncodeTime = zapcore.ISO8601TimeEncoder</span><br />
|
||
<span class="f_CodeExample"> </span><br />
|
||
<span class="f_CodeExample">opts := []zap.Option{</span><br />
|
||
<span class="f_CodeExample">zap.AddCaller(),</span><br />
|
||
<span class="f_CodeExample">}</span><br />
|
||
<span class="f_CodeExample"> </span><br />
|
||
<span class="f_CodeExample">logger := zap.New(zapcore.NewCore(</span><br />
|
||
<span class="f_CodeExample">zapcore.NewJSONEncoder(enc),</span><br />
|
||
<span class="f_CodeExample">zapcore.Lock(os.Stderr),</span><br />
|
||
<span class="f_CodeExample">zapcore.InfoLevel, // Required log level</span><br />
|
||
<span class="f_CodeExample">), opts...)</span><br />
|
||
<span class="f_CodeExample">logger = l.Named("MyService1")</span><br />
|
||
<span class="f_CodeExample"> </span><br />
|
||
<span class="f_CodeExample">zap.ReplaceGlobals(logger)</span><br />
|
||
<span class="f_CodeExample">}</span><br />
|
||
<span class="f_CodeExample">// Getting logger</span><br />
|
||
<span class="f_CodeExample">{</span><br />
|
||
<span class="f_CodeExample">l = zap.L()</span><br />
|
||
<span class="f_CodeExample">}</span><br />
|
||
<span class="f_CodeExample">// Showing log</span><br />
|
||
<span class="f_CodeExample">{</span><br />
|
||
<span class="f_CodeExample">l.Info("Hello zap-log")</span><br />
|
||
<span class="f_CodeExample">}</span></p>
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Probes</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Sometimes higher standards of availability, reliability, and innovation are demanded from microservices. For these cases Kubernetes provides a special feature called probes. A microservice developer designs and implements endpoints that can be accessed to get accurate information about a microservice’s health. When the microservices are deployed, the probes request information about their current state.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Portable services support Readiness and Liveness probes. They can be used separately or at the same time for one microservice. This probes ensure the microservice receives traffic only when it’s ready to accept it. In case of a failure, the microservice is restarted.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">We also recommend you to read the <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/" target="_blank" class="weblink">official documentation</a> and <a href="https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html" target="_blank" class="weblink">guidelines to working with probes</a>.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">You should describe the possible ways to perform checks with probes in the documentation clearly and in detail. If the description is wrong or the module developer uses it in a wrong way, the microservice or even the whole module will become inoperable. It is also critical to implement proper endpoints for the probes in the microservice.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">If you didn’t account for probes, specify this in the documentation. It is highly undesirable for the module developer to assign probes on their own.</span></p>
|
||
<h3 class="p_Heading3"><span class="f_Heading3">Liveness probe</span></h3>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">During the operation of a microservice, it can fall into a state that prevents it from functioning properly. The solution can be restarting the service. To check whether the microservice is in such a state, Liveness probes are used. They perform certain actions to confirm that your microservice is working as intended.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">You can use an HTTP request, open a TCP connection, or run a command in your container.</span></p>
|
||
<ul style="list-style-type:disc">
|
||
<li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 7px;"><span style="font-family: Inter;">To perform an HTTP probe, Kubernetes sends an HTTP GET request to the microservice. If the handler for the microservice’s path returns a success code, Kubernetes considers the microservice to be alive and healthy. If the handler returns a failure code, the microservice is restarted. Any code greater than or equal to 200 and less than 400 indicates success. Any other code indicates a failure.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 7px;"><span style="font-family: Inter;">A TCP probe uses a TCP socket. With the configuration of the portable service probe, Kubernetes attempts to open a socket. If it can establish a connection, the container is considered healthy. If it can’t, it is restarted.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 7px;"><span style="font-family: Inter;">In a command-based probe, a command specified in the portable service probe settings is performed. If the command runs successfully, it returns 0, and the microservice is considered healthy. If it returns a value other than 0, the microservice is restarted. </span></li></ul>
|
||
<h3 class="p_Heading3"><span class="f_Heading3">Readiness probe</span></h3>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Sometimes a microservice may not be ready to accept requests. For example, while preparatory initialization is performed at the startup or there is a dependency on other external microservices. In this cases, Kubernetes needs to wait until the microservice becomes ready. During this time, the microservice shouldn’t process requests sent to it. To handle situations like these, you can use Readiness probes. This allows the microservice to signal that it is not ready at the moment, and the request should be sent to another instance if there is one.</span></p>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">Readiness probes are configured in the same way as Liveness probes.</span></p>
|
||
<h2 class="p_Heading2"><span class="f_Heading2">Microservice documentation</span></h2>
|
||
<p style="line-height: 1.20; margin: 7px 0 16px 0;"><span style="font-family: Inter;">While developing a microservice, describe the following in the documentation:</span></p>
|
||
<ul style="list-style-type:disc">
|
||
<li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;">Provided API.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;">The port that is used to access the microservice.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;">The list of environment variables that the microservice can be configured with.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;">Whether Liveness and Readiness probes are set up and how to use them.</span></li><li style="line-height: 1.20; margin-top: 7px; margin-right: 0; margin-bottom: 16px;"><span style="font-family: Inter;"><a href="portable-services.html#add-service" class="topiclink">The unique name of the portable service</a> to configure the microservice deployment using <a href="configmap.html" class="topiclink">ConfigMap</a>.</span></li></ul>
|
||
|
||
<div class="bottom-nav">
|
||
|
||
<a id="prev-link" class="topic__navi_prev" href="portable-microservices.html">
|
||
<span class="bottom-nav__arrow bottom-nav__arrow--prev"></span> <span
|
||
class="bottom-nav__link">portable-microservices.html</span>
|
||
</a>
|
||
|
||
|
||
<a id="next-link" class="topic__navi_next" href="readiness.html">
|
||
<span class="bottom-nav__link">readiness.html</span> <span
|
||
class="bottom-nav__arrow bottom-nav__arrow--next"></span>
|
||
</a>
|
||
|
||
</div>
|
||
<!-- добавляет на страницу строку блок Была ли статья полезной? -->
|
||
<div class="feedback" id="feedback"><div class="feedback-help"><span><b>Was this helpful?</b></span><form action="" method="POST" class="feedback-form" id="feedback-form"><div class="feedback__popup feedback__popup-response" id="feedback__popup_thx" style="display: none;">Thanks for your feedback!</div><div class="feedback__popup" id="feedback__popup_why" style="display: none;"><div class="feedback__popup-header">Please specify why:</div><input type="radio" name="category" id="bad_recommendation" value="bad_recommendation"><label for="bad_recommendation">Recommendations did not help me</label><input type="radio" name="category" id="difficult_text" value="difficult_text"><label for="difficult_text">Article is hard to understand</label><input type="radio" name="category" id="no_answer" value="no_answer"><label for="no_answer">Didn`t answer my question</label><input type="radio" name="category" id="bad_header" value="bad_header"><label for="bad_header">Content does not match the topic</label><input type="radio" name="category" id="other_reason" value="other_reason"><label for="other_reason">Other</label></div><div class="feedback__popup" id="feedback__popup-other" style="display: none;"><div class="feedback__popup-header">How we can improve it?</div><textarea class="feedback__textarea" name="other" id=""></textarea><input type="submit" class="feedback__other-btn" value="Submit"></div><div class="feedback-form__btn-group"><input type="radio" name="useful" id="feedback__useful_yes" value="true"><label for="feedback__useful_yes"><img src="like.svg" class="small-img" alt="like"><spanclass="feedback-form__btn-group_yes-btn">Yes</spanclass="feedback-form__btn-group_yes-btn"></label><input type="radio" name="useful" id="feedback__useful_no" value="false"><label for="feedback__useful_no"><img src="dislike.svg" class="small-img" alt="dislike"><spanclass="feedback-form__btn-group_no-btn">No</spanclass="feedback-form__btn-group_no-btn"></label></div><select name="category"><option disabled="">Please specify why</option><option value="bad_recommendation" selected="">Recommendations did not help me</option><option value="difficult_text">Article is hard to understand</option><option value="no_answer">Didn`t answer my question</option><option value="bad_header">Content does not match the topic</option><option value="other_reason">Other</option></select><input type="submit"></form></div><div class="found_typo"><p style="margin: 0px; margin-top: 16px !important;"><span><b>Found a typo?</b></span> Select it and press <i>Ctrl+Enter</i> to send us feedback</p></div></div>
|
||
|
||
</section>
|
||
</div>
|
||
<aside class="article__sidebar" style="display:none">
|
||
<input type="checkbox" />
|
||
<div class="article__arrow"></div>
|
||
<div class="table-of-contents elma365-right" id="toc2Content">
|
||
<h3 class="h3-toc">In this topic</h3>
|
||
<nav id="toc2"></nav>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
</article>
|
||
</main>
|
||
<footer class="footer">
|
||
<div class="footer-container">
|
||
<div class="footer-mobile">
|
||
|
||
<ul class="footer-mobile__list"><li><a href="https://brix365.com/en/" target="_blank">BRIX</a></li><li><a href="https://tssdk.brix365.com/en/latest/" target="_blank">SDK</a></li><li><a href="https://api.brix365.com/en/" target="_blank">API</a></li></ul><ul class="footer-mobile__list"><li><a href="https://brix365.com/en/help/platform/get-trial.html">Platform</a></li><li><a href="https://brix365.com/en/help/ecm/ecm-functions.html">ECM</a></li><li><a href="https://brix365.com/en/help/service/service-functions.html">Service</a></li><li><a href="https://brix365.com/en/help/projects/projects-functions.html">Projects</a></li></ul>
|
||
|
||
|
||
</div>
|
||
<div class="footer-wrap">
|
||
|
||
<div><span class="mobile-question-popup">Send feedback</span><form method="POST" action class="question__popup question-xs" id="question__popup"><div class="question-wrap"><span class="close"></span><span class="title">Ask a question</span><label for="help_question" style="display: none;"></label><textarea name="help_question" id="help_question"></textarea><input type="submit" value="Send"></div></form><div class="hidden fade-in question-success-xs">Sent</div></div>
|
||
|
||
<div class="footer-flex-b">
|
||
<span class="footer-copy">© 2025 BRIX</span>
|
||
<ul class="footer-list">
|
||
|
||
<li class="footer-item">
|
||
<a href="#" class="arrow-top" style="display: block;"></a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</footer>
|
||
<iframe name="hmnavigation" style="display:none!important"></iframe>
|
||
<script src="./jquery-ui.js"></script>
|
||
<!--script src="//cdn.jsdelivr.net/npm/featherlight@1.7.14/release/featherlight.min.js" type="text/javascript" charset="utf-8"></script-->
|
||
<script src="./jquery.tocify.min.js"></script>
|
||
<script src="./TypoReporter.min.js"></script>
|
||
<script src="./google-search.js"></script>
|
||
<script src="./main.js"></script>
|
||
</body>
|
||
|
||
</html>
|