SUPPORT-9561: change file download to deferred one

This commit is contained in:
gulnaz 2025-11-25 15:45:23 +03:00
parent 4b6fe9a2db
commit 0173c1740f
19 changed files with 7298 additions and 3063 deletions

View file

@ -6,6 +6,8 @@ import ervu.model.fileupload.FileInfo;
import ervu.model.fileupload.FileStatus;
import ervu.model.fileupload.UploadOrgInfo;
import ru.micord.ervu.audit.model.AuditActionRequest;
import ru.micord.ervu.kafka.model.ExcerptData;
import ru.micord.ervu.kafka.model.ExcerptResponse;
import ru.micord.ervu.kafka.model.OrgInfo;
/**
@ -21,4 +23,7 @@ public interface AuditService {
void processDownloadEvent(HttpServletRequest request, long fileSize, String fileName,
int formatRegistry, String status, String s3FileUrl);
void processDownloadEvent(ExcerptData data, long fileSize, String fileName,
int formatRegistry, String status, String s3FileUrl);
}

View file

@ -20,6 +20,9 @@ import ru.micord.ervu.audit.model.*;
import ru.micord.ervu.audit.service.AuditKafkaPublisher;
import ru.micord.ervu.audit.service.AuditService;
import ru.micord.ervu.exception.JsonParsingException;
import ru.micord.ervu.kafka.model.Data;
import ru.micord.ervu.kafka.model.ExcerptData;
import ru.micord.ervu.kafka.model.ExcerptResponse;
import ru.micord.ervu.kafka.model.OrgInfo;
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
import ru.micord.ervu.security.esia.service.UlDataService;
@ -123,15 +126,29 @@ public class BaseAuditService implements AuditService {
}
@Override
public void processDownloadEvent(
HttpServletRequest request, long fileSize, String fileName, int formatRegistry,
String status, String s3FileUrl) {
public void processDownloadEvent(HttpServletRequest request, long fileSize, String fileName,
int formatRegistry, String status, String s3FileUrl) {
String userAccountId = jwtTokenService.getUserAccountId(request);
String eventTime = DateUtils.getClientDateTimeWithZone(
DateUtils.getClientDateTimeWithZoneFromRequest(request));
publishDownloadEvent(getEsiaOrgId(request), userAccountId, eventTime, fileSize, fileName,
formatRegistry, status, s3FileUrl);
}
@Override
public void processDownloadEvent(ExcerptData data, long fileSize, String fileName,
int formatRegistry,String status, String s3FileUrl) {
String eventTime = DateUtils.getClientDateTimeWithZone(data.getTimeZone());
publishDownloadEvent(data.getOrgId(), data.getPrnOid(), eventTime, fileSize, fileName,
formatRegistry, status, s3FileUrl);
}
private void publishDownloadEvent(String esiaOrgId, String esiaPersonId, String eventTime,
long fileSize, String fileName, int formatRegistry, String status, String s3FileUrl) {
AuditDownloadEvent event = new AuditDownloadEvent(
getEsiaOrgId(request),
userAccountId,
DateUtils.getClientDateTimeWithZoneFromRequest(request),
esiaOrgId,
esiaPersonId,
eventTime,
AuditConstants.getDownloadType(formatRegistry),
fileName,
s3FileUrl,

View file

@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
import ru.micord.ervu.audit.config.AuditDisableCondition;
import ru.micord.ervu.audit.model.AuditActionRequest;
import ru.micord.ervu.audit.service.AuditService;
import ru.micord.ervu.kafka.model.ExcerptData;
import ru.micord.ervu.kafka.model.OrgInfo;
/**
@ -32,4 +33,8 @@ public class StubAuditService implements AuditService {
@Override
public void processDownloadEvent(HttpServletRequest request, long fileSize, String fileName,
int formatRegistry, String status, String s3FileUrl) {}
@Override
public void processDownloadEvent(ExcerptData data, long fileSize, String fileName, int formatRegistry,
String status, String s3FileUrl) {}
}

View file

@ -0,0 +1,133 @@
package ru.micord.ervu.controller;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import ervu.client.fileupload.WebDavClient;
import ervu_lkrp_ul.ervu_lkrp_ul.db_beans.public_.tables.records.ExcerptHistoryRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.micord.ervu.audit.constants.AuditConstants;
import ru.micord.ervu.audit.service.AuditService;
import ru.micord.ervu.dao.ExcerptHistoryDao;
import ru.micord.ervu.kafka.exception.ExcerptException;
import ru.micord.ervu.kafka.model.Data;
import ru.micord.ervu.security.webbpm.jwt.UserIdsPair;
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
import ru.micord.ervu.util.UrlUtils;
/**
* @author Eduard Tihomirov
*/
@RestController
@RequestMapping("/excerpt")
public class ExcerptController {
@Autowired
@Qualifier("fileTemplate")
private KafkaTemplate<String, String> kafkaTemplate;
@Value("${ervu.kafka.excerpt.request.topic}")
private String requestTopic;
@Autowired
private AuditService auditService;
@Autowired
private WebDavClient webDavClient;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ExcerptHistoryDao excerptHistoryDao;
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public void requestExcerptUrl(@RequestBody Integer year, HttpServletRequest request) {
try {
String clientTimeZone = request.getHeader("Client-Time-Zone");
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
String ervuId = userIdsPair.getErvuId();
String prnOid = userIdsPair.getEsiaUserId();
Data data = new Data();
data.setErvuId(ervuId);
data.setPrnOid(prnOid);
String offset = ZonedDateTime.now(TimeZone.getTimeZone(clientTimeZone).toZoneId())
.getOffset().getId();
data.setTimeZone(offset);
data.setYear(year);
kafkaTemplate.send(requestTopic, objectMapper.writeValueAsString(data)).get();
excerptHistoryDao.delete(ervuId, prnOid);
excerptHistoryDao.insert(ervuId, prnOid);
}
catch (Exception e) {
throw new ExcerptException(e);
}
}
@GetMapping("/download")
public ResponseEntity<Resource> getExcerptFile(HttpServletRequest request) {
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
String ervuId = userIdsPair.getErvuId();
String prnOid = userIdsPair.getEsiaUserId();
String fileUrl = null;
String fileName = null;
long fileSize = 0;
try {
Optional<ExcerptHistoryRecord> historyRecord = excerptHistoryDao.get(ervuId, prnOid);
if (historyRecord.isEmpty()) {
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
return ResponseEntity.noContent().build();
}
else {
fileUrl = historyRecord.get().getUrl();
fileName = UrlUtils.extractFileNameFromUrl(fileUrl);
ResponseEntity<Resource> responseEntity = webDavClient.webDavDownloadFile(fileUrl);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
fileSize = responseEntity.getHeaders().getContentLength();
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.SUCCESS_STATUS_TYPE, fileUrl
);
}
else {
excerptHistoryDao.delete(ervuId, prnOid);
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
}
return responseEntity;
}
}
catch (Exception e) {
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
throw new ExcerptException(e);
}
}
@GetMapping("/status")
public String getStatus() {
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
return excerptHistoryDao.getStatus(userIdsPair.getErvuId(), userIdsPair.getEsiaUserId());
}
}

View file

@ -0,0 +1,99 @@
package ru.micord.ervu.dao;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Optional;
import ervu_lkrp_ul.ervu_lkrp_ul.db_beans.public_.tables.records.ExcerptHistoryRecord;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.springframework.stereotype.Repository;
import static ervu_lkrp_ul.ervu_lkrp_ul.db_beans.public_.tables.ExcerptHistory.EXCERPT_HISTORY;
import static org.jooq.impl.DSL.case_;
import static org.jooq.impl.DSL.coalesce;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.select;
/**
* @author gulnaz
*/
@Repository
public class ExcerptHistoryDao {
private final DSLContext dslContext;
public ExcerptHistoryDao(DSLContext dslContext) {
this.dslContext = dslContext;
}
public Optional<ExcerptHistoryRecord> get(String ervuId, String prnOid) {
return dslContext.select(EXCERPT_HISTORY.ID)
.from(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.ID.eq(
select(DSL.max(EXCERPT_HISTORY.ID))
.from(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.ERVU_ID.eq(ervuId)
.and(EXCERPT_HISTORY.PRN_OID.eq(prnOid)))
))
.fetchOptionalInto(ExcerptHistoryRecord.class);
}
public String getStatus(String ervuId, String prnOid) {
return dslContext.select(coalesce(
field(
select(
case_()
.when(EXCERPT_HISTORY.DATETIME.isNull(), "in-progress")
.else_("ready")
)
.from(EXCERPT_HISTORY)
.where(
EXCERPT_HISTORY.ERVU_ID.eq(ervuId)
.and(EXCERPT_HISTORY.PRN_OID.eq(prnOid))
)
),
"none"
)).fetchAnyInto(String.class);
}
public void insert(String ervuId, String prnOid) {
dslContext.insertInto(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.ERVU_ID, ervuId)
.set(EXCERPT_HISTORY.PRN_OID, prnOid)
.execute();
}
public void insert(String ervuId, String prnOid, String url) {
dslContext.insertInto(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.ERVU_ID, ervuId)
.set(EXCERPT_HISTORY.PRN_OID, prnOid)
.set(EXCERPT_HISTORY.URL, url)
.set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now()))
.execute();
}
public void update(Long id, String url) {
dslContext.update(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.URL, url)
.set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now()))
.where(EXCERPT_HISTORY.ID.eq(id))
.execute();
}
public void delete(String ervuId, String prnOid) {
dslContext.deleteFrom(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.ERVU_ID.eq(ervuId)
.and(EXCERPT_HISTORY.PRN_OID.eq(prnOid)))
.execute();
}
public void deleteOld() {
dslContext.deleteFrom(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.DATETIME.le(
Timestamp.valueOf(LocalDateTime.now().minus(1, ChronoUnit.HOURS))))
.execute();
}
}

View file

@ -42,8 +42,6 @@ public class ReplyingKafkaConfig {
private String groupId;
@Value("${ervu.kafka.reply.timeout:30}")
private long replyTimeout;
@Value("${ervu.kafka.excerpt.reply.topic}")
private String excerptReplyTopic;
@Value("${kafka.auth_sec_proto}")
private String securityProtocol;
@Value("${kafka.auth_sasl_module}")
@ -119,8 +117,7 @@ public class ReplyingKafkaConfig {
@Bean("ervuContainer")
public ConcurrentMessageListenerContainer<String, String> ervuContainer(
@Qualifier("ervuContainerFactory") ConcurrentKafkaListenerContainerFactory<String, String> factory) {
return factory.createContainer(orgReplyTopic, excerptReplyTopic,
journalReplyTopic, avReplyTopic);
return factory.createContainer(orgReplyTopic, journalReplyTopic, avReplyTopic);
}
@Bean("validateContainer")

View file

@ -1,96 +0,0 @@
package ru.micord.ervu.kafka.controller;
import java.time.ZonedDateTime;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import ervu.client.fileupload.WebDavClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.micord.ervu.audit.constants.AuditConstants;
import ru.micord.ervu.audit.service.AuditService;
import ru.micord.ervu.kafka.exception.ExcerptException;
import ru.micord.ervu.kafka.exception.ExcerptResponseException;
import ru.micord.ervu.kafka.model.Data;
import ru.micord.ervu.kafka.model.ExcerptResponse;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
import ru.micord.ervu.security.webbpm.jwt.UserIdsPair;
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
import ru.micord.ervu.util.UrlUtils;
/**
* @author Eduard Tihomirov
*/
@RestController
public class ErvuKafkaController {
@Autowired
private ReplyingKafkaService<String, String> replyingKafkaService;
@Autowired
private AuditService auditService;
@Autowired
private WebDavClient webDavClient;
@Value("${ervu.kafka.excerpt.reply.topic}")
private String requestReplyTopic;
@Value("${ervu.kafka.excerpt.request.topic}")
private String requestTopic;
@Autowired
private ObjectMapper objectMapper;
@GetMapping(value = "/kafka/excerpt")
public ResponseEntity<Resource> getExcerptFile(HttpServletRequest request) {
String fileUrl = null;
String fileName = null;
long fileSize = 0;
try {
String clientTimeZone = request.getHeader("Client-Time-Zone");
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
Data data = new Data();
data.setErvuId(userIdsPair.getErvuId());
data.setPrnOid(userIdsPair.getEsiaUserId());
String offset = ZonedDateTime.now(TimeZone.getTimeZone(clientTimeZone).toZoneId())
.getOffset().getId();
data.setTimeZone(offset);
String kafkaResponse = replyingKafkaService.sendMessageAndGetReply(requestTopic,
requestReplyTopic, objectMapper.writeValueAsString(data));
ExcerptResponse excerptResponse = objectMapper.readValue(kafkaResponse, ExcerptResponse.class);
if (!excerptResponse.getSuccess()) {
throw new ExcerptResponseException(
"Error with getting excerpt url " + excerptResponse.getMessage());
}
else if (excerptResponse.getData() == null || excerptResponse.getData().getFileUrl() == null
|| excerptResponse.getData().getFileUrl().isEmpty()) {
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
return ResponseEntity.noContent().build();
}
fileUrl = excerptResponse.getData().getFileUrl();
fileName = UrlUtils.extractFileNameFromUrl(excerptResponse.getData().getFileUrl());
ResponseEntity<Resource> responseEntity = webDavClient.webDavDownloadFile(fileUrl);
fileSize = responseEntity.getHeaders().getContentLength();
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.SUCCESS_STATUS_TYPE, fileUrl
);
return responseEntity;
}
catch (Exception e) {
auditService.processDownloadEvent(request, fileSize, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
throw new ExcerptException(e);
}
}
}

View file

@ -0,0 +1,77 @@
package ru.micord.ervu.kafka.listener;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import ru.micord.ervu.audit.constants.AuditConstants;
import ru.micord.ervu.audit.service.AuditService;
import ru.micord.ervu.dao.ExcerptHistoryDao;
import ru.micord.ervu.kafka.exception.ExcerptException;
import ru.micord.ervu.kafka.exception.ExcerptResponseException;
import ru.micord.ervu.kafka.model.ExcerptData;
import ru.micord.ervu.kafka.model.ExcerptResponse;
import ru.micord.ervu.util.UrlUtils;
/**
* @author gulnaz
*/
public class ExcerptListener {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ExcerptHistoryDao excerptHistoryDao;
@Autowired
private AuditService auditService;
@KafkaListener(
id = "${ervu.kafka.group.id}",
topics = "${ervu.kafka.excerpt.reply.topic}",
containerFactory = "fileContainerFactory")
public void listen(String kafkaResponse) {
String fileUrl = null;
String fileName = null;
ExcerptData data = new ExcerptData();
try {
ExcerptResponse excerptResponse = objectMapper.readValue(kafkaResponse, ExcerptResponse.class);
if (!excerptResponse.getSuccess()) {
throw new ExcerptResponseException(
"Error with getting excerpt url " + excerptResponse.getMessage());
}
else if (excerptResponse.getData() == null || excerptResponse.getData().getFileUrl() == null
|| excerptResponse.getData().getFileUrl().isEmpty()) {
if (excerptResponse.getData() != null) {
data = excerptResponse.getData();
}
auditService.processDownloadEvent(data, 0, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
return;
}
data = excerptResponse.getData();
fileUrl = data.getFileUrl();
fileName = UrlUtils.extractFileNameFromUrl(fileUrl);
String ervuId = excerptResponse.getData().getOrgId();
String prnOid = excerptResponse.getData().getPrnOid();
AtomicReference<String> fileRef = new AtomicReference<>(fileUrl);
excerptHistoryDao.get(ervuId, prnOid)
.ifPresentOrElse(
record -> excerptHistoryDao.update(record.getId(), fileRef.get()),
() -> excerptHistoryDao.insert(ervuId, prnOid, fileRef.get())
);
}
catch (Exception e) {
auditService.processDownloadEvent(data, 0, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl
);
throw new ExcerptException(e);
}
}
}

View file

@ -16,6 +16,7 @@ public class Data implements Serializable {
private String ervuId;
private String prnOid;
private String timeZone;
private int year;
public String getErvuId() {
return ervuId;
@ -40,4 +41,12 @@ public class Data implements Serializable {
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}

View file

@ -11,6 +11,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
public class ExcerptData implements Serializable {
private static final long serialVersionUID = 1L;
private String orgId;
private String prnOid;
private String timeZone;
private String fileUrl;
public String getOrgId() {
@ -21,6 +23,22 @@ public class ExcerptData implements Serializable {
this.orgId = orgId;
}
public String getPrnOid() {
return prnOid;
}
public void setPrnOid(String prnOid) {
this.prnOid = prnOid;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getFileUrl() {
return fileUrl;
}

View file

@ -0,0 +1,25 @@
package ru.micord.ervu.scheduler;
import net.javacrumbs.shedlock.core.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import ru.micord.ervu.dao.ExcerptHistoryDao;
/**
* @author gulnaz
*/
@Service
public class ExcerptCleanScheduler {
private final ExcerptHistoryDao excerptHistoryDao;
public ExcerptCleanScheduler(ExcerptHistoryDao excerptHistoryDao) {
this.excerptHistoryDao = excerptHistoryDao;
}
@Scheduled(cron = "${excerpt.cleanup.cron:0 */30 * * * *}")
@SchedulerLock(name = "oldExcerptFilesCleaning")
public void cleanOld() {
excerptHistoryDao.deleteOld();
}
}

View file

@ -43,7 +43,12 @@ public final class DateUtils {
public static String getClientDateTimeWithZoneFromRequest(HttpServletRequest request) {
String clientTimeZone = request.getHeader("Client-Time-Zone");
return getClientDateTimeWithZone(clientTimeZone);
}
public static String getClientDateTimeWithZone(String clientTimeZone) {
ZoneId zoneId;
try {
zoneId = ZoneId.of(clientTimeZone);
}

File diff suppressed because it is too large Load diff

View file

@ -119,10 +119,24 @@
.webbpm.ervu_lkrp_ul ervu-download-file-button {
display: block;
}
.webbpm.ervu_lkrp_ul .fieldset text + ervu-download-file-button {
.webbpm.ervu_lkrp_ul .fieldset ervu-download-file-button,
.webbpm.ervu_lkrp_ul year-combo-box .selectize-input {
margin-top: var(--indent-mini);
}
.webbpm.ervu_lkrp_ul year-combo-box .selectize-dropdown-content {
padding: 5px 0;
}
.webbpm.ervu_lkrp_ul .message-clock {
background: url(../img/svg/clock-32x32.svg) no-repeat 0 0;
display: block;
font-size: var(--l-size-text-primary);
height: 32px;
margin: var(--indent-mini) 0;
padding-left: var(--indent-big);
}
.webbpm.ervu_lkrp_ul .btn,
.webbpm.ervu_lkrp_ul .fieldset .btn-main:not(.info):not(.link) .btn,
.webbpm.ervu_lkrp_ul .modal.show button-component.btn-main:not(.info):not(.link) .btn,
@ -1422,4 +1436,4 @@
}
.webbpm.ervu_lkrp_ul .plain-text {
margin-bottom: 0;
}
}

View file

@ -1,8 +1,6 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from "@angular/core";
import {AbstractButton, MessagesService, NotNull, ObjectRef} from "@webbpm/base-package";
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {InMemoryStaticGrid} from "../grid/InMemoryStaticGrid";
import {Subscription} from "rxjs";
/**
* @author: Eduard Tihomirov
@ -14,13 +12,9 @@ import {Subscription} from "rxjs";
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ErvuDownloadFileButton extends AbstractButton {
private httpClient: HttpClient;
private messageService: MessagesService;
private gridLoadedSubscription: Subscription;
@ObjectRef()
@NotNull()
public grid: InMemoryStaticGrid;
@NotNull()
public fileName: string;
@ -36,29 +30,10 @@ export class ErvuDownloadFileButton extends AbstractButton {
super.initialize();
this.httpClient = this.injector.get(HttpClient);
this.messageService = this.injector.get(MessagesService);
if (this.grid.isInitialized() && this.grid.getRowDataSize() > 0) {
this.setEnabled(true);
this.setVisible(true);
}
this.gridLoadedSubscription = this.grid.gridLoaded.subscribe(() => {
if (this.grid.getRowDataSize() > 0) {
this.setEnabled(true);
this.setVisible(true);
}
else {
this.setEnabled(false);
this.setVisible(false);
}
});
}
ngOnDestroy() {
super.ngOnDestroy();
this.gridLoadedSubscription.unsubscribe();
}
public doClickActions(): Promise<any> {
return this.httpClient.get('kafka/excerpt', {
return this.httpClient.get('excerpt/download', {
responseType: 'blob',
headers: new HttpHeaders({'Client-Time-Zone' : Intl.DateTimeFormat().resolvedOptions().timeZone}),
observe: 'response'

View file

@ -0,0 +1,67 @@
import {
AbstractButton, AnalyticalScope,
Behavior,
ComboBox, Dialog,
MessagesService,
NotNull,
ObjectRef
} from "@webbpm/base-package";
import {HttpClient, HttpHeaders} from "@angular/common/http";
@AnalyticalScope(AbstractButton)
export class ErvuFileRequestButton extends Behavior {
@NotNull()
@ObjectRef()
public year: ComboBox;
@NotNull()
@ObjectRef()
public beforeRequestDialog: Dialog;
@NotNull()
@ObjectRef()
public afterRequestDialog: Dialog;
private button: AbstractButton;
private httpClient: HttpClient;
private messageService: MessagesService;
private onClickFunction: Function;
private onYearValueChange: Function;
initialize() {
super.initialize();
this.button = this.getScript(AbstractButton);
this.httpClient = this.injector.get(HttpClient);
this.messageService = this.injector.get(MessagesService);
this.onClickFunction = () => {
if (!this.year.getValue()) {
this.messageService.error("Не выбран период");
return;
}
this.httpClient.post("excerpt", this.year.getValue(), {
headers: new HttpHeaders(
{'Client-Time-Zone': Intl.DateTimeFormat().resolvedOptions().timeZone})
}).toPromise()
.then(() => {
this.beforeRequestDialog.hide();
this.afterRequestDialog.show();
})
.catch(e => this.messageService.error(e));
};
this.onYearValueChange = () => this.button.setEnabled(this.year.getValue());
}
bindEvents() {
super.bindEvents();
this.button.addClickListener(this.onClickFunction);
this.year.addUserChangeValueListener(this.onYearValueChange);
}
unbindEvents() {
super.unbindEvents();
this.button.removeClickListener(this.onClickFunction);
this.year.removeUserChangeValueListener(this.onYearValueChange);
}
}

View file

@ -0,0 +1,71 @@
import {AbstractButton, AnalyticalScope, Behavior, NotNull, ObjectRef, Text} from "@webbpm/base-package";
import {Subscription} from "rxjs";
import {InMemoryStaticGrid} from "../grid/InMemoryStaticGrid";
import {OnDestroy} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {ExcerptStatus} from "../enum/ExcerptStatus";
@AnalyticalScope(AbstractButton)
export class ErvuFileRequestDialogButton extends Behavior implements OnDestroy {
@ObjectRef()
@NotNull()
public grid: InMemoryStaticGrid;
@ObjectRef()
@NotNull()
public text: Text;
@ObjectRef()
@NotNull()
public downloadButton: AbstractButton;
@NotNull()
public requestSentMsg: string;
private button: AbstractButton;
private httpClient: HttpClient;
private gridLoadedSubscription: Subscription;
private fileStatus: string = ExcerptStatus.NONE;
initialize() {
super.initialize();
this.button = this.getScript(AbstractButton);
this.httpClient = this.injector.get(HttpClient);
this.gridLoadedSubscription = this.grid.gridLoaded.subscribe(() => {
this.button.setEnabled(this.grid.getRowDataSize() > 0
&& this.fileStatus !== ExcerptStatus.IN_PROGRESS);
this.button.setVisible(this.grid.getRowDataSize() > 0);
});
}
start() {
super.start();
this.getFileStatus()
.then(status => {
this.fileStatus = status;
if (this.grid.isInitialized() && this.grid.getRowDataSize() > 0) {
this.button.setEnabled(status !== ExcerptStatus.IN_PROGRESS);
this.button.setVisible(true);
}
if (status === ExcerptStatus.IN_PROGRESS) {
this.button.setTooltip(this.requestSentMsg);
this.text.setValue(this.requestSentMsg);
}
this.downloadButton.setEnabled(status === ExcerptStatus.READY);
this.downloadButton.setVisible(status === ExcerptStatus.READY);
});
}
private getFileStatus(): Promise<string> {
return this.httpClient.get('excerpt/status', {observe: 'response'}).toPromise()
.then(res => res.body.toString());
}
ngOnDestroy() {
this.gridLoadedSubscription.unsubscribe();
}
}

View file

@ -0,0 +1,5 @@
export enum ExcerptStatus {
NONE = 'none',
IN_PROGRESS = 'in-progress',
READY = 'ready'
}

View file

@ -2037,13 +2037,6 @@
<scripts id="73f52c22-5182-4860-8ee6-b9ba164ed460"/>
<scripts id="2129eba5-aac3-41d1-ba50-0a2f4b5f0a32"/>
<scripts id="865a51e1-80f5-4064-a7d2-2b251b33bdec"/>
<children id="358d1918-2e9b-4123-a8b5-8189a1789291">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
<componentRootId>358d1918-2e9b-4123-a8b5-8189a1789291</componentRootId>
<name>Горизонтальный контейнер</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="097a2141-13d0-4b15-ac5f-5c310b3753f7">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>097a2141-13d0-4b15-ac5f-5c310b3753f7</componentRootId>
@ -2066,7 +2059,7 @@
<entry>
<key>initialValue</key>
<value>
<simple>"Запросите выписку, чтобы посмотреть журнал взаимодействий за весь период"</simple>
<simple>"Запросите выписку о переданных сведениях по сотрудникам в Военные комиссариаты"</simple>
</value>
</entry>
<entry>
@ -2084,67 +2077,429 @@
<enabled>false</enabled>
</scripts>
</children>
<children id="a3c68e2f-424c-4908-9983-b5e3adf8805b">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
<componentRootId>a3c68e2f-424c-4908-9983-b5e3adf8805b</componentRootId>
<name>Hbox</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
<scripts id="b6068710-0f31-48ec-8e03-c0c1480a40c0"/>
<scripts id="fe04d7fb-6c5b-46c4-b723-667732d81f4f"/>
<scripts id="5c566210-2a60-4048-a2d1-84c7dd023248"/>
<scripts id="3171b2e1-b4af-4335-95fa-1b2592604b84"/>
<children id="cddb82f9-6e93-4fde-a30c-60bbced3b380">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>cddb82f9-6e93-4fde-a30c-60bbced3b380</componentRootId>
<name>Кнопка диалога запроса выписки</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<properties>
<entry>
<key>caption</key>
<value>
<simple>"Запросить выписку"</simple>
</value>
</entry>
<entry>
<key>disabled</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>false</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="d99b7472-aae1-4f14-b2f7-065423a9a1ab">
<classRef type="TS">
<className>ErvuFileRequestDialogButton</className>
<packageName>ervu.component.button</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>downloadButton</key>
<value>
<simple>{"objectId":"2528ea8a-3e3f-4968-a973-8e9ac1ca4326","packageName":"ervu.component.button","className":"ErvuDownloadFileButton","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>grid</key>
<value>
<simple>{"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>requestSentMsg</key>
<value>
<simple>"Запрос на формирование выписки отправлен"</simple>
</value>
</entry>
<entry>
<key>text</key>
<value>
<simple>{"objectId":"097a2141-13d0-4b15-ac5f-5c310b3753f7","packageName":"component","className":"Text","type":"TS"}</simple>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="2528ea8a-3e3f-4968-a973-8e9ac1ca4326">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>2528ea8a-3e3f-4968-a973-8e9ac1ca4326</componentRootId>
<name>Скачать</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<expanded>false</expanded>
<removed>true</removed>
</scripts>
<scripts id="38036714-7fff-4404-98d3-b0f5cc846368">
<classRef type="TS">
<className>ErvuDownloadFileButton</className>
<packageName>ervu.component.button</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>caption</key>
<value>
<simple>"Скачать выписку"</simple>
</value>
</entry>
<entry>
<key>disabled</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>fileName</key>
<value>
<simple>"Выписка.xlsx"</simple>
</value>
</entry>
<entry>
<key>noFileMessage</key>
<value>
<simple>"Нет записей в выписке журнала взаимодействия"</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>false</simple>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="cb657c69-1023-4462-ada6-03c1a9fbcb8e">
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
<componentRootId>cb657c69-1023-4462-ada6-03c1a9fbcb8e</componentRootId>
<name>Dialog: запросить выписку</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c"/>
<scripts id="48d405ee-5991-4027-bfee-113a895bf8f8"/>
<scripts id="b463917a-16fc-42db-9c92-9c1027e9232e"/>
<scripts id="24a13b10-fec4-420e-aa2e-5af0ec41326a"/>
<scripts id="5f57bb31-85b0-4692-9f1f-d6369dea6e95"/>
<children id="55a6bd55-8a44-4b4f-8070-9dc36d2bcf3a">
<prototypeId>b310f98a-69c6-4e7b-8cdb-f1ab9f9c0d94</prototypeId>
<componentRootId>55a6bd55-8a44-4b4f-8070-9dc36d2bcf3a</componentRootId>
<name>Выберите период</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="23992f0e-94ed-4fb4-b4d1-dc6ad7f13227">
<enabled>false</enabled>
<properties>
<entry>
<key>collectible</key>
<value>
<simple>false</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="efb0fec7-9951-4b36-bbda-fa17aa002d74">
<enabled>false</enabled>
<expanded>false</expanded>
</scripts>
<scripts id="4d028ea6-e4a3-4acf-bd60-de7aa1a78f71">
<enabled>false</enabled>
<expanded>false</expanded>
</scripts>
<scripts id="9f543b36-92e3-4a63-b8db-a4d7e852113e">
<enabled>false</enabled>
<expanded>false</expanded>
</scripts>
<scripts id="47f307b6-79a7-4c9a-96d6-6ee423565f02">
<enabled>false</enabled>
<expanded>false</expanded>
</scripts>
<scripts id="ec1e9370-303a-4a7e-948f-27ef7687cd03">
<enabled>false</enabled>
<expanded>false</expanded>
</scripts>
<scripts id="8dc2d4a1-3734-450c-8136-6bb76ac67f19">
<classRef type="TS">
<className>YearComboBox</className>
<packageName>ervu.component.combobox</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>label</key>
<value>
<simple>"Выберите период"</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>true</simple>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="6a2c076b-7a39-4afc-bb43-49fff00b21e3">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>6a2c076b-7a39-4afc-bb43-49fff00b21e3</componentRootId>
<name>Запросить выписку</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<properties>
<entry>
<key>caption</key>
<value>
<simple>"Запросить выписку"</simple>
</value>
</entry>
<entry>
<key>disabled</key>
<value>
<simple>true</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="c92fdf96-a832-4f5d-ad06-5873382fc045">
<classRef type="TS">
<className>ErvuFileRequestButton</className>
<packageName>ervu.component.button</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>afterRequestDialog</key>
<value>
<simple>{"objectId":"6ed640f7-eab1-4dcc-99c0-c9a49c85292f","packageName":"component","className":"Dialog","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>beforeRequestDialog</key>
<value>
<simple>{"objectId":"cb657c69-1023-4462-ada6-03c1a9fbcb8e","packageName":"component","className":"Dialog","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>year</key>
<value>
<simple>{"objectId":"55a6bd55-8a44-4b4f-8070-9dc36d2bcf3a","packageName":"component.field","className":"ComboBox","type":"TS"}</simple>
</value>
</entry>
</properties>
</scripts>
</children>
</children>
<children id="6ed640f7-eab1-4dcc-99c0-c9a49c85292f">
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
<componentRootId>6ed640f7-eab1-4dcc-99c0-c9a49c85292f</componentRootId>
<name>Dialog: запрос отправлен</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c"/>
<scripts id="48d405ee-5991-4027-bfee-113a895bf8f8"/>
<scripts id="b463917a-16fc-42db-9c92-9c1027e9232e"/>
<scripts id="24a13b10-fec4-420e-aa2e-5af0ec41326a"/>
<scripts id="5f57bb31-85b0-4692-9f1f-d6369dea6e95"/>
<children id="ead2d930-7157-4d98-b778-67f6a378bcd7">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>ead2d930-7157-4d98-b778-67f6a378bcd7</componentRootId>
<name>Заголовок</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
<properties>
<entry>
<key>collectible</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>cssClasses</key>
<value>
<item id="278ba196-69c3-4f3f-ac32-6c217a7129a7" removed="false">
<value>
<simple>"title"</simple>
</value>
</item>
</value>
</entry>
<entry>
<key>initialValue</key>
<value>
<simple>"Запрос отправлен"</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="737b67e2-295f-4356-a1e1-9419344d8c85"/>
<scripts id="a6ccccd9-354c-4725-9d34-c716cf626048"/>
<scripts id="d38c1af5-2bfe-41cd-ab0f-67040f498127"/>
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
<enabled>false</enabled>
</scripts>
</children>
<children id="882c5346-4c05-43eb-9675-8fc860565429">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>882c5346-4c05-43eb-9675-8fc860565429</componentRootId>
<name>Сообщение</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
<properties>
<entry>
<key>collectible</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>initialValue</key>
<value>
<simple>"Выписка будет сформирована Государственной информационной системой \"Единый реестр воинского учета\" (ГИС ЕРВУ) и направлена в ваш личный кабинет Реестра повесток"</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="737b67e2-295f-4356-a1e1-9419344d8c85"/>
<scripts id="a6ccccd9-354c-4725-9d34-c716cf626048"/>
<scripts id="d38c1af5-2bfe-41cd-ab0f-67040f498127"/>
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
<enabled>false</enabled>
</scripts>
</children>
<children id="b84e5d1f-ad34-44b9-aca4-29b2083aea37">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>b84e5d1f-ad34-44b9-aca4-29b2083aea37</componentRootId>
<name>Время</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
<properties>
<entry>
<key>collectible</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>cssClasses</key>
<value>
<item id="5b32e81b-8c6b-47e6-9779-be0b36003695" removed="false">
<value>
<simple>"message-clock"</simple>
</value>
</item>
</value>
</entry>
<entry>
<key>initialValue</key>
<value>
<simple>"Услуга будет оказана в течение дня"</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="737b67e2-295f-4356-a1e1-9419344d8c85"/>
<scripts id="a6ccccd9-354c-4725-9d34-c716cf626048"/>
<scripts id="d38c1af5-2bfe-41cd-ab0f-67040f498127"/>
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
<enabled>false</enabled>
</scripts>
</children>
<children id="b8655a1c-b30f-426c-bbd4-5799281f0752">
<prototypeId>c8dfe691-a84a-48da-b79e-6298d90db71d</prototypeId>
<componentRootId>b8655a1c-b30f-426c-bbd4-5799281f0752</componentRootId>
<name>Navigation: В личный кабинет</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<properties>
<entry>
<key>caption</key>
<value>
<simple>"В личный кабинет"</simple>
</value>
</entry>
<entry>
<key>navigateTo</key>
<value>
<simple>"/"</simple>
</value>
</entry>
</properties>
</scripts>
</children>
</children>
</children>
<children id="6ed640f7-eab1-4dcc-99c0-c9a49c85292f">
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
<componentRootId>6ed640f7-eab1-4dcc-99c0-c9a49c85292f</componentRootId>
<name>Dialog: запрос отправлен</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="cddb82f9-6e93-4fde-a30c-60bbced3b380">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>cddb82f9-6e93-4fde-a30c-60bbced3b380</componentRootId>
<name>Кнопка диалога запроса выписки</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="cb657c69-1023-4462-ada6-03c1a9fbcb8e">
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
<componentRootId>cb657c69-1023-4462-ada6-03c1a9fbcb8e</componentRootId>
<name>Dialog</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="2528ea8a-3e3f-4968-a973-8e9ac1ca4326">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>2528ea8a-3e3f-4968-a973-8e9ac1ca4326</componentRootId>
<name>Кнопка</name>
<name>Скачать</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<expanded>false</expanded>
<removed>true</removed>
</scripts>
<scripts id="38036714-7fff-4404-98d3-b0f5cc846368">
<classRef type="TS">
<className>ErvuDownloadFileButton</className>
<packageName>ervu.component.button</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>caption</key>
<value>
<simple>"Запросить выписку"</simple>
</value>
</entry>
<entry>
<key>disabled</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>fileName</key>
<value>
<simple>"Выписка.xlsx"</simple>
</value>
</entry>
<entry>
<key>grid</key>
<value>
<simple>{"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>noFileMessage</key>
<value>
<simple>"Нет записей в выписке журнала взаимодействия"</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>false</simple>
</value>
</entry>
</properties>
</scripts>
<removed>true</removed>
</children>
<children id="78640b5d-37d1-4940-aafc-fc7a38b907cf">
<children id="f4ae195f-3afe-473e-ba9e-72c966b55b25">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>78640b5d-37d1-4940-aafc-fc7a38b907cf</componentRootId>
<name>Action Controller</name>
<componentRootId>f4ae195f-3afe-473e-ba9e-72c966b55b25</componentRootId>
<name>AС: видимость текста</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
@ -2152,7 +2507,9 @@
<entry>
<key>elseActions</key>
<value>
<item id="80889965-e277-41cc-bbc5-ea7948ad8b60" removed="false">
<item id="0d72a8ee-d2f3-4e93-9a4a-2b91c70b63d6" removed="true"/>
<item id="46eb6480-4c66-473e-926d-622fc73b25a7" removed="true"/>
<item id="6124572f-0dcd-48f1-80b9-08b84357aaf4" removed="false">
<value>
<complex>
<entry>
@ -2192,13 +2549,13 @@
<entry>
<key>eventRefs</key>
<value>
<item id="6f361a45-7ce6-4ca5-b927-ed4db7b2e39c" removed="false">
<item id="a6dcb50f-3d74-406c-b44d-5df6f199ab70" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"2528ea8a-3e3f-4968-a973-8e9ac1ca4326","packageName":"ervu.component.button","className":"ErvuDownloadFileButton","type":"TS"}</simple>
<simple>{"objectId":"cddb82f9-6e93-4fde-a30c-60bbced3b380","packageName":"component.button","className":"Button","type":"TS"}</simple>
</value>
</entry>
<entry>
@ -2219,7 +2576,7 @@
<entry>
<key>conditions</key>
<value>
<item id="558f60e6-3e60-4fc8-b790-dc7ebd17b4d4" removed="false">
<item id="890c0449-3274-4408-abb9-ec01e8a64ad8" removed="false">
<value>
<complex>
<entry>
@ -2243,7 +2600,7 @@
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"2528ea8a-3e3f-4968-a973-8e9ac1ca4326","packageName":"ervu.component.button","className":"ErvuDownloadFileButton","type":"TS"}</simple>
<simple>{"objectId":"cddb82f9-6e93-4fde-a30c-60bbced3b380","packageName":"component.button","className":"Button","type":"TS"}</simple>
</value>
</entry>
<entry>
@ -2301,7 +2658,9 @@
<entry>
<key>thenActions</key>
<value>
<item id="db6a9474-f16f-4015-8103-655173944b7e" removed="false">
<item id="80b3e9b1-d416-49c0-ba90-28224e564510" removed="true"/>
<item id="bafd5b4b-0600-4bb8-a05f-49e7e7d8ff83" removed="true"/>
<item id="50e53dfc-b185-4b63-b1a2-cbac45d6445a" removed="false">
<value>
<complex>
<entry>
@ -2341,6 +2700,330 @@
</properties>
</scripts>
</children>
<children id="55a6bd55-8a44-4b4f-8070-9dc36d2bcf3a">
<prototypeId>b310f98a-69c6-4e7b-8cdb-f1ab9f9c0d94</prototypeId>
<componentRootId>55a6bd55-8a44-4b4f-8070-9dc36d2bcf3a</componentRootId>
<name>Выберите период</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="6a2c076b-7a39-4afc-bb43-49fff00b21e3">
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
<componentRootId>6a2c076b-7a39-4afc-bb43-49fff00b21e3</componentRootId>
<name>Запросить выписку</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="7fbfc96c-0c1a-46e0-938b-ec45e75341bd">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>7fbfc96c-0c1a-46e0-938b-ec45e75341bd</componentRootId>
<name>AC: показать диалог для запроса</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
<properties>
<entry>
<key>eventRefs</key>
<value>
<item id="1ebba0cc-903d-4d4a-ace0-b883a8d72fef" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"cddb82f9-6e93-4fde-a30c-60bbced3b380","packageName":"component.button","className":"Button","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>propertyName</key>
<value>
<simple>"clickEvent"</simple>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
<entry>
<key>ifCondition</key>
<value>
<complex>
<entry>
<key>logicalOperation</key>
<value>
<simple>null</simple>
</value>
</entry>
</complex>
</value>
</entry>
<entry>
<key>thenActions</key>
<value>
<item id="ec91ecee-66a4-4c63-9005-d0b37d262ee7" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"cb657c69-1023-4462-ada6-03c1a9fbcb8e","packageName":"component","className":"Dialog","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"show"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<simple>null</simple>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="8825f9d1-53b1-438f-9b32-4850eba28bd7">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>8825f9d1-53b1-438f-9b32-4850eba28bd7</componentRootId>
<name>AC: доступность кнопки</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
<properties>
<entry>
<key>eventRefs</key>
<value>
<item id="447ef47f-e5ac-45a1-ab6c-9975db866093" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"6ed640f7-eab1-4dcc-99c0-c9a49c85292f","packageName":"component","className":"Dialog","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>propertyName</key>
<value>
<simple>"hideDialogEvent"</simple>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
<entry>
<key>ifCondition</key>
<value>
<complex>
<entry>
<key>logicalOperation</key>
<value>
<simple>null</simple>
</value>
</entry>
</complex>
</value>
</entry>
<entry>
<key>thenActions</key>
<value>
<item id="fa958867-a8c8-4129-8821-705da43a225e" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"cddb82f9-6e93-4fde-a30c-60bbced3b380","packageName":"component.button","className":"Button","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setEnabled"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>boolean</className>
<packageName></packageName>
</implRef>
<simple>false</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
<item id="15c453fa-2b8f-497b-bdb3-d863af9ac436" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"cddb82f9-6e93-4fde-a30c-60bbced3b380","packageName":"component.button","className":"Button","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setTooltip"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>string</className>
<packageName></packageName>
</implRef>
<simple>"Запрос на формирование выписки отправлен"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
<item id="ac6fbec0-1ee0-4b2c-b934-00327039e72a" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"097a2141-13d0-4b15-ac5f-5c310b3753f7","packageName":"component","className":"Text","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setValue"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>string</className>
<packageName></packageName>
</implRef>
<simple>"Запрос на формирование выписки отправлен"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
<item id="de8f7972-0364-4fa8-b94f-c9d6bc9d9107" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"2528ea8a-3e3f-4968-a973-8e9ac1ca4326","packageName":"ervu.component.button","className":"ErvuDownloadFileButton","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setEnabled"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>boolean</className>
<packageName></packageName>
</implRef>
<simple>false</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
<item id="484cc7fa-46d2-4f98-95b8-992d64649e79" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"2528ea8a-3e3f-4968-a973-8e9ac1ca4326","packageName":"ervu.component.button","className":"ErvuDownloadFileButton","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setVisible"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>boolean</className>
<packageName></packageName>
</implRef>
<simple>false</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="0480ebf1-7636-46f4-9b68-7a30c08b7d4d">
<prototypeId>f4ca0e36-67d2-4882-9032-96718d6892da</prototypeId>
<componentRootId>0480ebf1-7636-46f4-9b68-7a30c08b7d4d</componentRootId>
<name>Download button</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="f4d7dfb7-67e6-41bd-bef6-ae9751ce2088">
<prototypeId>3057d447-6d17-48a8-b096-b14ea88d17e8</prototypeId>
<componentRootId>f4d7dfb7-67e6-41bd-bef6-ae9751ce2088</componentRootId>
@ -2348,13 +3031,6 @@
<container>false</container>
<removed>true</removed>
</children>
<children id="484748b4-a03d-4254-a7f3-fec2402e7866">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
<componentRootId>484748b4-a03d-4254-a7f3-fec2402e7866</componentRootId>
<name>Горизонтальный контейнер</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="87481ea6-30aa-4002-81d0-421e066298ff">
<prototypeId>e32ae1f5-5b14-45f1-abb6-f52c34b3b570</prototypeId>
<componentRootId>87481ea6-30aa-4002-81d0-421e066298ff</componentRootId>
@ -2384,5 +3060,12 @@
<removed>true</removed>
</children>
</children>
<children id="9078f42f-c838-4d38-9e46-4419d12eb80d">
<prototypeId>a4d442cf-72a8-431e-815a-490959083787</prototypeId>
<componentRootId>9078f42f-c838-4d38-9e46-4419d12eb80d</componentRootId>
<name>SecurityFeatures</name>
<container>true</container>
<removed>true</removed>
</children>
</rootObjects>
</xmlPage>