SUPPORT-8772:add new fileUpload

This commit is contained in:
adel.ka 2024-12-17 14:30:54 +03:00
parent ceecd93b79
commit 0c1c5bbdcf
21 changed files with 2282 additions and 20 deletions

View file

@ -1,6 +1,10 @@
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.util.IntrospectorCleanupListener;
@ -9,6 +13,7 @@ import org.springframework.web.util.IntrospectorCleanupListener;
* Spring scans for initializers automatically
*/
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private static final Logger LOGGER = LoggerFactory.getLogger(WebAppInitializer.class);
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
@ -28,4 +33,39 @@ public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServlet
protected Class<?>[] getServletConfigClasses() {
return new Class[0];
}
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
// read from env or assign default values
int maxFileSize = parseOrDefault("ERVU_FILE_UPLOAD_MAX_FILE_SIZE", 5242880);
int maxRequestSize = parseOrDefault("ERVU_FILE_UPLOAD_MAX_REQUEST_SIZE", 6291456);
int fileSizeThreshold = parseOrDefault("ERVU_FILE_UPLOAD_FILE_SIZE_THRESHOLD", 0);
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(
"/tmp",
maxFileSize,
maxRequestSize,
fileSizeThreshold);
registration.setMultipartConfig(multipartConfigElement);
LOGGER.info("Max file upload size is set to: " + multipartConfigElement.getMaxFileSize());
LOGGER.info("Max file upload request size is set to: " + multipartConfigElement.getMaxRequestSize());
LOGGER.info("File size threshold is set to: " + multipartConfigElement.getFileSizeThreshold());
}
private int parseOrDefault(String envVar, int defaultVal) {
String envVarValue = System.getenv(envVar);
if (envVar == null) {
LOGGER.info("Environment variable {} is null, using default value: {}", envVar, defaultVal);
return defaultVal;
}
try {
return Integer.parseInt(envVarValue);
} catch (NumberFormatException e) {
LOGGER.info("Environment variable {} is not an integer, using default value: {}", envVar, defaultVal);
return defaultVal;
}
}
}

View file

@ -0,0 +1,40 @@
package ru.micord.ervu_dashboard.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import ru.micord.ervu_dashboard.service.ErvuFileUploadService;
/**
* @author Adel Kalimullin
*/
@RestController
@RequestMapping("/upload")
public class ErvuFileUploadController {
private static final Logger LOGGER = LoggerFactory.getLogger(ErvuFileUploadController.class);
private final ErvuFileUploadService fileUploadService;
public ErvuFileUploadController(ErvuFileUploadService fileUploadService) {
this.fileUploadService = fileUploadService;
}
@PostMapping()
public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("No file provided.");
}
try {
fileUploadService.save(file);
return ResponseEntity.ok().body("File successfully uploaded.");
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
return ResponseEntity.internalServerError().body("An error occurred while uploading file.");
}
}
}

View file

@ -0,0 +1,82 @@
package ru.micord.ervu_dashboard.dao;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jooq.DSLContext;
import org.jooq.InsertOnDuplicateSetMoreStep;
import org.jooq.TableField;
import org.springframework.stereotype.Repository;
import ru.micord.ervu_dashboard.db_beans.appeals.tables.records.AppealsListRecord;
import static ru.micord.ervu_dashboard.db_beans.appeals.Tables.APPEALS_LIST;
/**
* @author Adel Kalimullin
*/
@Repository
public class ErvuFileUploadDao {
private final DSLContext dslContext;
public ErvuFileUploadDao(DSLContext dslContext) {
this.dslContext = dslContext;
}
public void save(List<Map<String, String>> records) {
LocalDateTime uploadDate = LocalDateTime.now();
var queries = records.stream().map(record -> {
Map<TableField<AppealsListRecord, ?>, Object> fieldsMap = createFieldsMap(record, uploadDate);
Map<TableField<AppealsListRecord, ?>, Object> updateFieldsMap = new HashMap<>(fieldsMap);
updateFieldsMap.remove(APPEALS_LIST.NUMBER);
return dslContext.insertInto(APPEALS_LIST)
.set(fieldsMap)
.onConflict(APPEALS_LIST.NUMBER)
.doUpdate()
.set(updateFieldsMap)
.where(APPEALS_LIST.NUMBER.eq((Integer)fieldsMap.get(APPEALS_LIST.NUMBER)));
}).toList();
dslContext.batch(queries).execute();
}
private Map<TableField<AppealsListRecord, ?>, Object> createFieldsMap(Map<String, String> valueMap, LocalDateTime uploadDate) {
Map<TableField<AppealsListRecord, ?>, Object> fieldsMap = new HashMap<>();
fieldsMap.put(APPEALS_LIST.NUMBER, Integer.valueOf(valueMap.get(APPEALS_LIST.NUMBER.getComment())));
fieldsMap.put(APPEALS_LIST.EPGU_NUM, valueMap.get(APPEALS_LIST.EPGU_NUM.getComment()));
fieldsMap.put(APPEALS_LIST.SOURCE, valueMap.get(APPEALS_LIST.SOURCE.getComment()));
fieldsMap.put(APPEALS_LIST.REGION, valueMap.get(APPEALS_LIST.REGION.getComment()));
fieldsMap.put(APPEALS_LIST.CATEGORY, valueMap.get(APPEALS_LIST.CATEGORY.getComment()));
fieldsMap.put(APPEALS_LIST.SUBCATEGORY, valueMap.get(APPEALS_LIST.SUBCATEGORY.getComment()));
fieldsMap.put(APPEALS_LIST.FACT, valueMap.get(APPEALS_LIST.FACT.getComment()));
fieldsMap.put(APPEALS_LIST.INCOMING_ORG, valueMap.get(APPEALS_LIST.INCOMING_ORG.getComment()));
fieldsMap.put(APPEALS_LIST.CURRENT_ORG, valueMap.get(APPEALS_LIST.CURRENT_ORG.getComment()));
fieldsMap.put(APPEALS_LIST.INCOMING_DATE, valueMap.get(APPEALS_LIST.INCOMING_DATE.getComment()));
fieldsMap.put(APPEALS_LIST.PLAN_END_DATE, valueMap.get(APPEALS_LIST.PLAN_END_DATE.getComment()));
fieldsMap.put(APPEALS_LIST.FACT_END_DATE, valueMap.get(APPEALS_LIST.FACT_END_DATE.getComment()));
fieldsMap.put(APPEALS_LIST.STAGE, valueMap.get(APPEALS_LIST.STAGE.getComment()));
fieldsMap.put(APPEALS_LIST.STATUS, valueMap.get(APPEALS_LIST.STATUS.getComment()));
fieldsMap.put(APPEALS_LIST.OVERDUE, valueMap.get(APPEALS_LIST.OVERDUE.getComment()));
fieldsMap.put(APPEALS_LIST.FAST_TRACK, valueMap.get(APPEALS_LIST.FAST_TRACK.getComment()));
fieldsMap.put(APPEALS_LIST.FZ, valueMap.get(APPEALS_LIST.FZ.getComment()));
fieldsMap.put(APPEALS_LIST.SOLUTION_TYPE, valueMap.get(APPEALS_LIST.SOLUTION_TYPE.getComment()));
fieldsMap.put(APPEALS_LIST.SENT_BY_EMAIL_TO_NOT_CONNECTED_FOIV, valueMap.get(APPEALS_LIST.SENT_BY_EMAIL_TO_NOT_CONNECTED_FOIV.getComment()));
fieldsMap.put(APPEALS_LIST.RESPONSE_EVALUTION, valueMap.get(APPEALS_LIST.RESPONSE_EVALUTION.getComment()));
fieldsMap.put(APPEALS_LIST.RECONSIDERATION, valueMap.get(APPEALS_LIST.RECONSIDERATION.getComment()));
fieldsMap.put(APPEALS_LIST.COORDINATOR_ORG, valueMap.get(APPEALS_LIST.COORDINATOR_ORG.getComment()));
fieldsMap.put(APPEALS_LIST.COORDINATOR_FIO, valueMap.get(APPEALS_LIST.COORDINATOR_FIO.getComment()));
fieldsMap.put(APPEALS_LIST.CONTRACTOR_ORG, valueMap.get(APPEALS_LIST.CONTRACTOR_ORG.getComment()));
fieldsMap.put(APPEALS_LIST.CONTRACTOR_FIO, valueMap.get(APPEALS_LIST.CONTRACTOR_FIO.getComment()));
fieldsMap.put(APPEALS_LIST.HEAD_ORG, valueMap.get(APPEALS_LIST.HEAD_ORG.getComment()));
fieldsMap.put(APPEALS_LIST.HEAD_FIO, valueMap.get(APPEALS_LIST.HEAD_FIO.getComment()));
fieldsMap.put(APPEALS_LIST.ISSUE_DATE, valueMap.get(APPEALS_LIST.ISSUE_DATE.getComment()));
fieldsMap.put(APPEALS_LIST.UPLOAD_DATE, Timestamp.valueOf(uploadDate));
return fieldsMap;
}
}

View file

@ -0,0 +1,19 @@
package ru.micord.ervu_dashboard.exception;
/**
* @author Adel Kalimullin
*/
public class FileUploadException extends RuntimeException {
public FileUploadException(String message) {
super(message);
}
public FileUploadException(String message, Throwable cause) {
super(message, cause);
}
public FileUploadException(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,19 @@
package ru.micord.ervu_dashboard.exception;
/**
* @author Adel Kalimullin
*/
public class MissingHeaderException extends RuntimeException {
public MissingHeaderException(String message, Throwable cause) {
super(message, cause);
}
public MissingHeaderException(String message) {
super(message);
}
public MissingHeaderException(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,27 @@
package ru.micord.ervu_dashboard.service;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.micord.ervu_dashboard.dao.ErvuFileUploadDao;
/**
* @author Adel Kalimullin
*/
@Service
public class ErvuFileUploadService {
private final FileParser xlsFileParser;
private final ErvuFileUploadDao fileUploadDao;
public ErvuFileUploadService(FileParser xlsFileParser, ErvuFileUploadDao fileUploadDao) {
this.xlsFileParser = xlsFileParser;
this.fileUploadDao = fileUploadDao;
}
public void save(MultipartFile file) {
List<Map<String, String>> maps = xlsFileParser.parseFile(file);
fileUploadDao.save(maps);
}
}

View file

@ -0,0 +1,16 @@
package ru.micord.ervu_dashboard.service;
import java.util.List;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Adel Kalimullin
*/
public interface FileParser {
List<Map<String, String>> parseFile(MultipartFile file);
}

View file

@ -0,0 +1,98 @@
package ru.micord.ervu_dashboard.service;
import java.io.InputStream;
import java.util.*;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.micord.ervu_dashboard.exception.FileUploadException;
import ru.micord.ervu_dashboard.exception.MissingHeaderException;
/**
* @author Adel Kalimullin
*/
@Service
public class XlsParser implements FileParser {
private static final List<String> REQUIRED_HEADERS = Arrays.asList(
"Номер", "Номер ЕПГУ", "Источник", "Верхнеуровневый ЛКО", "Категория", "Подкатегория",
"Факт", "Организация, в которую поступило сообщение",
"Организация, в которой находится сообщение",
"Дата поступления", "Дата планируемого завершения работ",
"Дата фактического завершения работ",
"Стадия", "Статус", "Просрочено", "Фаст-трек", "ФЗ", "Тип решения",
"Направлено по email в ФОИВ, не подключенный к ПОС", "Оценка ответа заявителем",
"Повторное рассмотрение", "Организация координатора", "ФИО координатора",
"Организация исполнителя", "ФИО исполнителя", "Организация руководителя", "ФИО руководителя",
"Дата вынесения"
);
@Override
public List<Map<String, String>> parseFile(MultipartFile file) {
List<Map<String, String>> records = new ArrayList<>();
try (InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream)) {
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
List<String> headers = new ArrayList<>();
if (rowIterator.hasNext()) {
Row headerRow = rowIterator.next();
for (Cell cell : headerRow) {
headers.add(cell.getStringCellValue());
}
validateHeaders(headers);
}
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Map<String, String> rowData = new HashMap<>();
for (int i = 0; i < headers.size(); i++) {
Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
rowData.put(headers.get(i), getCellValue(cell));
}
records.add(rowData);
}
}
catch (Exception e) {
throw new FileUploadException("Error parsing the file", e);
}
return records;
}
private void validateHeaders(List<String> headers) {
for (String requiredHeader : REQUIRED_HEADERS) {
if (!headers.contains(requiredHeader)) {
throw new MissingHeaderException("Required header is missing:" + requiredHeader);
}
}
}
private String getCellValue(Cell cell) {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getLocalDateTimeCellValue().toString();
}
else {
return String.valueOf((int) cell.getNumericCellValue());
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case BLANK:
return "";
default:
return cell.toString();
}
}
private List<String> getRequiredHeaders(String rawHeaders) {
return Arrays.stream(rawHeaders.split(";"))
.map(String::trim)
.toList();
}
}

View file

@ -104,5 +104,13 @@
</sql>
</changeSet>
<changeSet id="0002" author="adel.ka" dbms="postgresql">
<comment>add primary key</comment>
<addPrimaryKey
columnNames="number"
constraintName="pk_appeals_list"
tableName="appeals_list"
schemaName="appeals" />
</changeSet>
</databaseChangeLog>

View file

@ -5,3 +5,8 @@ DB_APP_PASSWORD=ervu-dashboard
DB_APP_HOST=10.10.31.119
DB_APP_PORT=5432
DB_APP_NAME=ervu-dashboard-copy
ERVU_FILE_UPLOAD_XLSX_REQUIRED_HEADERS='Номер;Номер ЕПГУ;Источник;Верхнеуровневый ЛКО;Категория;Подкатегория;Факт;Организация, в которую поступило сообщение;Организация, в которой находится сообщение;Дата поступления;Дата планируемого завершения работ;Дата фактического завершения работ;Стадия;Статус;Просрочено;Фаст-трек;ФЗ;Тип решения;Направлено по email в ФОИВ, не подключенный к ПОС;Оценка ответа заявителем;Повторное рассмотрение;Организация координатора;ФИО координатора;Организация исполнителя;ФИО исполнителя;Организация руководителя;ФИО руководителя;'
ERVU_FILE_UPLOAD_MAX_FILE_SIZE=5242880
ERVU_FILE_UPLOAD_MAX_REQUEST_SIZE=6291456
ERVU_FILE_UPLOAD_FILE_SIZE_THRESHOLD=0

View file

@ -4997,6 +4997,11 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"ng2-file-upload": {
"version": "1.3.0",
"resolved": "https://repo.micord.ru/repository/npm-all/ng2-file-upload/-/ng2-file-upload-1.3.0.tgz",
"integrity": "sha512-Pudxik6LWYsT8hNiEW7RfjgGWAnvfQywxwJYMdt1snTUe+KnlRc/QqPv3QEQW6plXTanuLkYz/TbqilSfSHOsw=="
},
"ngx-cookie": {
"version": "3.0.1",
"resolved": "https://repo.micord.ru/repository/npm-all/ngx-cookie/-/ngx-cookie-3.0.1.tgz",

View file

@ -49,10 +49,11 @@
"jsgantt-improved": "2.0.10-cg",
"moment": "2.30.1",
"moment-timezone": "0.5.46",
"ngx-treeview": "10.0.2-micord.2",
"ng2-file-upload": "^1.3.0",
"ngx-cookie": "3.0.1",
"ngx-international-phone-number": "1.0.6",
"ngx-toastr": "10.2.0-cg",
"ngx-treeview": "10.0.2-micord.2",
"popper.js": "1.14.7",
"reflect-metadata": "0.1.13",
"rxjs": "6.4.0",

View file

@ -1540,6 +1540,17 @@
}
}
.webbpm .ervu-file-upload .file-drop-zone {
position: relative;
display: flex;
justify-content: center;
padding: 152px 0 66px 0;
border: 1px dashed #0e243b;
border-radius: 16px;
background: #a58888;
}
/* ErvuFileUpload end *
/*
grid-checkbox

View file

@ -0,0 +1,31 @@
<div [id]="getObjectId()"
class="ervu-file-upload"
[ngbTooltip]="tooltip | emptyIfNull">
<div ng2FileDrop
[uploader]="uploader"
class="file-drop-zone"
*ngIf="(!maxFilesToUpload || uploader.queue.length < maxFilesToUpload) && isDropZoneVisible">
<span class="select-file-field-text">{{selectFileFieldText}}</span>
<button class="select-file-btn" (click)="openFileChooseDialog()">{{selectFileButtonName}}</button>
</div>
<!-- input is out of file-drop-zone because after change ngIf condition input doesn't firing events -->
<input type="file"
class="file-input"
ng2FileSelect
[uploader]="uploader"
[multiple]="!maxFilesToUpload || maxFilesToUpload > 1"
[accept]="getExtensions()"
hidden>
<div class="selected-file-list" *ngIf="isFilesListVisible">
<div class="selected-file" *ngFor="let item of uploader.queue">
<span class="selected-file-name">{{item?.file?.name}}</span>
<span class="selected-file-size" *ngIf="displayFileSize">{{item?.file?.size/1024/1024 | number: '.2'}} MB</span>
<button class="selected-file-delete-btn" (click)="removeFile(item)">{{removeFileButtonName}}</button>
</div>
</div>
<div class="file-upload-progress" *ngIf="displayProgressBar && isProgressBarVisible">
<div class="file-upload-progress-bar"
role="progressbar"
[ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>

View file

@ -0,0 +1,229 @@
import {
AppConfigService,
Event,
InputControl,
MessagesService,
NotNull,
UnsupportedOperationError,
Visible,
} from "@webbpm/base-package";
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef,} from "@angular/core";
import {FileItem, FileLikeObject, FileUploader} from "ng2-file-upload";
@Component({
selector: 'ervu-file-upload',
templateUrl: './../../../../../src/resources/template/ervu-dashboard/ErvuFileUpload.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ErvuFileUpload extends InputControl {
private static readonly BACKEND_URL: string = "backend.context";
@NotNull("true") public selectFileFieldText: string;
@NotNull("true") public selectFileButtonName: string;
@NotNull("true") public removeFileButtonName: string;
public maxFileSizeMb: number;
public extensionFilter: string[] = [];
public maxFilesToUpload: number;
@NotNull("true") public displayFileSize: boolean = false;
@NotNull("true") public displayProgressBar: boolean = false;
@Visible("false") public uploader: FileUploader;
@Visible("false") public fileAddedEvent: Event<any> = new Event<any>();
@Visible("false") public fileDeletedEvent: Event<any> = new Event<any>();
@Visible("false") public fileUploadStartEvent: Event<any> = new Event<any>();
@Visible("false") public fileUploadEndEvent: Event<any> = new Event<any>();
@Visible("false") public fileUploadFailedEvent: Event<any> = new Event<any>();
public isDropZoneVisible: boolean = true;
public isFilesListVisible: boolean = true;
public isProgressBarVisible: boolean = false;
private fileInputEl: HTMLInputElement;
private url: string = '/backend/upload';
private messagesService: MessagesService;
private isUploadErrorOccurred = false;
private appConfigService: AppConfigService;
constructor(el: ElementRef, cd: ChangeDetectorRef) {
super(el, cd);
this.uploader = new FileUploader({url: this.url});
}
initialize() {
super.initialize();
this.messagesService = this.injector.get(MessagesService);
this.appConfigService = this.injector.get(AppConfigService);
this.url =
`/${this.appConfigService.getParamValue(ErvuFileUpload.BACKEND_URL)}/upload`;
this.uploader.setOptions({
url: this.url,
autoUpload: false,
filters: [{
name: 'extension', fn: (item: any): boolean => {
if (!this.extensionFilter.length) {
return true;
}
const fileExtension = item.name.substring(
item.name.lastIndexOf('.') + 1, item.name.length);
for (let ext of this.extensionFilter) {
if (ext.toUpperCase() === fileExtension.toUpperCase()) {
return true;
}
}
return false;
}
}],
maxFileSize: this.maxFileSizeMb
? this.maxFileSizeMb * 1024 * 1024
: undefined,
queueLimit: this.maxFilesToUpload
? this.maxFilesToUpload
: undefined,
headers: [{
name: "Client-Time-Zone",
value: Intl.DateTimeFormat().resolvedOptions().timeZone
}]
});
this.setUploaderMethods();
}
ngAfterViewInit() {
super.ngAfterViewInit();
this.fileInputEl = this.el.nativeElement.querySelector('.file-input');
}
openFileChooseDialog() {
this.fileInputEl.click();
}
@Visible() uploadFiles() {
this.uploader.uploadAll();
}
removeFile(item: FileItem) {
item.remove();
this.fileInputEl.value = null;
this.fileDeletedEvent.trigger();
this.cd.markForCheck();
}
private setUploaderMethods() {
this.uploader.onBeforeUploadItem = (fileItem: FileItem) => {
//refresh headers
this.uploader.setOptions({
headers: [{
name: "Client-Time-Zone",
value: Intl.DateTimeFormat().resolvedOptions().timeZone
}]
});
this.fileUploadStartEvent.trigger();
this.isDropZoneVisible = false;
this.isFilesListVisible = false;
this.isProgressBarVisible = true;
this.cd.markForCheck();
};
this.uploader.onErrorItem = (item: FileItem, response: string) => {
this.fileUploadFailedEvent.trigger();
this.uploader.cancelAll();
this.messagesService.error(`Не удалось отправить следующие файлы: ${item.file.name},` +
` ${this.uploader.getNotUploadedItems()
.map(notUploadeditem => notUploadeditem.file.name)
.join(', ')}.`);
this.uploader.clearQueue();
this.isDropZoneVisible = true;
this.isFilesListVisible = true;
this.isProgressBarVisible = false;
this.isUploadErrorOccurred = true;
this.cd.markForCheck();
};
this.uploader.onCompleteAll = () => {
if (!this.isUploadErrorOccurred) {
this.uploader.clearQueue();
this.fileUploadEndEvent.trigger();
this.isProgressBarVisible = false;
this.cd.markForCheck();
}
};
this.uploader.onAfterAddingFile = (fileItem: FileItem) => {
this.fileAddedEvent.trigger();
}
this.uploader.onWhenAddingFileFailed = (item: FileLikeObject, filter: any, options: any) => {
switch (filter.name) {
case "fileSize":
this.messagesService.error(
`Размер файла ${item.name} превышает предельно допустимый = ${this.maxFileSizeMb} MB`);
break;
case "queueLimit":
this.messagesService.error(`Не удалось добавить файл ${item.name}. ` +
`Достигнуто максимальное количество файлов для загрузки = ${this.maxFilesToUpload}`);
break;
case "extension":
this.messagesService.error(`Файл ${item.name} имеет недопустимое расширение.`);
break;
default:
this.messagesService.error(`Не удалось добавить файл ${item.name}.`);
}
this.fileInputEl.value = null;
this.cd.markForCheck();
};
}
@Visible() getExtensions(): string {
if (this.extensionFilter) {
return this.extensionFilter
.map(s => '.' + s)
.join(',')
}
return undefined;
}
subscribeToModelChange() {
//empty because there is no ngModel here
}
unsubscribeToModelChange() {
//empty because there is no ngModel here
}
@Visible() getPresentationValue(): string {
let fileNames: string = '';
let fileItems: FileItem[] = this.uploader.queue;
if (fileItems) {
fileItems.forEach((fileItem) => {
fileNames += fileItem.file.name;
});
}
return fileNames;
}
@Visible() getValue(): File[] {
return this.uploader.queue.map(fileItem => fileItem._file);
}
getValueAsModel(): any {
throw new UnsupportedOperationError("Unsupported operation");
}
setValue(value: any): any {
throw new UnsupportedOperationError("Unsupported operation");
}
@Visible()
public reset() {
//don't use super because there is no ngModel here
this.uploader.clearQueue();
this.fileInputEl.value = null;
this.isDropZoneVisible = true;
this.isFilesListVisible = true;
this.isProgressBarVisible = false;
this.isUploadErrorOccurred = false;
this.cd.markForCheck();
}
}

View file

@ -25,6 +25,8 @@ import {DropdownTreeViewComponent} from "../../component/field/DropdownTreeViewC
import {DropdownTreeviewSelectComponent} from "../../component/external/ngx-treeview/dropdown-treeview-select/dropdown-treeview-select.component";
import {TreeviewModule} from "ngx-treeview";
import {DataDateComponent} from "./component/data-date.component";
import {ErvuFileUpload} from "../../ervu-dashboard/component/field/ErvuFileUpload";
import {FileUploadModule} from "ng2-file-upload";
registerLocaleData(localeRu);
export const DIRECTIVES = [
@ -37,7 +39,8 @@ export const DIRECTIVES = [
forwardRef(() => FilterContainer),
forwardRef(() => DropdownTreeViewComponent),
forwardRef(() => DropdownTreeviewSelectComponent),
forwardRef(() => DataDateComponent)
forwardRef(() => DataDateComponent),
forwardRef(() => ErvuFileUpload)
];
@NgModule({
@ -52,7 +55,8 @@ export const DIRECTIVES = [
AgGridModule,
RouterModule,
InternationalPhoneNumberModule,
TreeviewModule.forRoot()
TreeviewModule.forRoot(),
FileUploadModule
],
declarations: [
DIRECTIVES

View file

@ -63,7 +63,8 @@
'tslib': 'npm:tslib/tslib.js',
'ngx-international-phone-number': 'npm:ngx-international-phone-number/ngx-international-phone-number.umd.js',
'google-libphonenumber': 'npm:google-libphonenumber/dist/libphonenumber.js',
'ngx-treeview': 'npm:ngx-treeview'
'ngx-treeview': 'npm:ngx-treeview',
'ng2-file-upload': 'npm:ng2-file-upload/bundles/ng2-file-upload.umd.js'
},
packages: {
'webbpm': { main: 'main', defaultExtension: 'js'},

View file

@ -63,7 +63,8 @@
'tslib': 'npm:tslib/tslib.js',
'ngx-international-phone-number': 'npm:ngx-international-phone-number/ngx-international-phone-number.umd.js',
'google-libphonenumber': 'npm:google-libphonenumber/dist/libphonenumber.js',
'ng2-dropdown-treeview': 'npm:ng2-dropdown-treeview'
'ng2-dropdown-treeview': 'npm:ng2-dropdown-treeview',
'ng2-file-upload': 'npm:ng2-file-upload/bundles/ng2-file-upload.umd.js'
},
packages: {
'preview': { main: './modules/preview/preview.main', defaultExtension: 'js'},

View file

@ -19,7 +19,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<enable.version.in.url>false</enable.version.in.url>
<joda-time.version>2.9.2</joda-time.version>
<webbpm-platform.version>3.185.0</webbpm-platform.version>
<webbpm-platform.version>3.187.0-SNAPSHOT</webbpm-platform.version>
<wbp.overall-timeout>72000</wbp.overall-timeout>
</properties>
<dependencyManagement>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlComponent>
<id>f4a465bc-4712-4965-9855-42502cfcf7ec</id>
<name>ErvuFileUpload</name>
<internal>false</internal>
<versions>
<studioVersion>3.185.1</studioVersion>
<packageVersions>
<entry>
<key>ru.cg.webbpm.packages.base.resources</key>
<value>3.185.0</value>
</entry>
</packageVersions>
</versions>
<rootObject id="0e7967fd-2bce-4181-a3f5-f4537ea94598">
<name>ErvuFileUpload</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
</rootObject>
</xmlComponent>

File diff suppressed because it is too large Load diff