mirror of
https://gitee.com/eolink_admin/postcat.git
synced 2024-12-04 20:58:01 +08:00
Merge branch 'feat/preview' of github.com:eolinker/eoapi into feat/preview
This commit is contained in:
commit
caacb923e9
@ -5,7 +5,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve -c web -o",
|
"start": "ng serve -c web -o",
|
||||||
"start:cn":"ng serve -c webCn -o",
|
"start:cn": "ng serve -c webCn -o",
|
||||||
"build": "node ./build/build.js",
|
"build": "node ./build/build.js",
|
||||||
"build:web": "node ./build/build.js web",
|
"build:web": "node ./build/build.js web",
|
||||||
"ng:serve": "ng serve -c web -o",
|
"ng:serve": "ng serve -c web -o",
|
||||||
@ -76,7 +76,6 @@
|
|||||||
"karma-coverage-istanbul-reporter": "3.0.3",
|
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||||
"karma-jasmine": "5.1.0",
|
"karma-jasmine": "5.1.0",
|
||||||
"karma-jasmine-html-reporter": "2.0.0",
|
"karma-jasmine-html-reporter": "2.0.0",
|
||||||
"lodash": "4.17.21",
|
|
||||||
"node-polyfill-webpack-plugin": "2.0.0",
|
"node-polyfill-webpack-plugin": "2.0.0",
|
||||||
"postcss": "8.4.14",
|
"postcss": "8.4.14",
|
||||||
"tailwindcss": "3.1.4",
|
"tailwindcss": "3.1.4",
|
||||||
|
@ -3,11 +3,10 @@ import { SafeResourceUrl } from '@angular/platform-browser';
|
|||||||
import { SidebarService } from 'eo/workbench/browser/src/app/shared/components/sidebar/sidebar.service';
|
import { SidebarService } from 'eo/workbench/browser/src/app/shared/components/sidebar/sidebar.service';
|
||||||
import { Message } from 'eo/workbench/browser/src/app/shared/services/message/message.model';
|
import { Message } from 'eo/workbench/browser/src/app/shared/services/message/message.model';
|
||||||
import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service';
|
import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service';
|
||||||
import { Subject, takeUntil } from 'rxjs';
|
import { Subject, takeUntil, debounceTime } from 'rxjs';
|
||||||
import { isElectron } from 'eo/shared/common/common';
|
import { isElectron } from 'eo/shared/common/common';
|
||||||
import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service';
|
import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service';
|
||||||
import { IS_SHOW_REMOTE_SERVER_NOTIFICATION } from 'eo/workbench/browser/src/app/shared/services/storage/storage.service';
|
import { IS_SHOW_REMOTE_SERVER_NOTIFICATION } from 'eo/workbench/browser/src/app/shared/services/storage/storage.service';
|
||||||
import { debounce } from 'lodash';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'eo-pages',
|
selector: 'eo-pages',
|
||||||
@ -26,6 +25,7 @@ export class PagesComponent implements OnInit {
|
|||||||
return this.remoteService.dataSourceText;
|
return this.remoteService.dataSourceText;
|
||||||
}
|
}
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
private rawChange$: Subject<string> = new Subject<string>();
|
||||||
get isShowNotification() {
|
get isShowNotification() {
|
||||||
return !this.isRemote && this.isShow;
|
return !this.isRemote && this.isShow;
|
||||||
}
|
}
|
||||||
@ -35,11 +35,15 @@ export class PagesComponent implements OnInit {
|
|||||||
public sidebar: SidebarService,
|
public sidebar: SidebarService,
|
||||||
private messageService: MessageService,
|
private messageService: MessageService,
|
||||||
private remoteService: RemoteService
|
private remoteService: RemoteService
|
||||||
) {}
|
) {
|
||||||
|
this.rawChange$.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
|
this.updateState();
|
||||||
|
});
|
||||||
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.watchSidebarItemChange();
|
this.watchSidebarItemChange();
|
||||||
this.watchRemoteServerChange();
|
this.watchRemoteServerChange();
|
||||||
this.updateState();
|
this.rawChange$.next('');
|
||||||
}
|
}
|
||||||
private watchSidebarItemChange() {
|
private watchSidebarItemChange() {
|
||||||
this.sidebar.appChanged$.subscribe(() => {
|
this.sidebar.appChanged$.subscribe(() => {
|
||||||
@ -48,7 +52,7 @@ export class PagesComponent implements OnInit {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
//add loading
|
//add loading
|
||||||
this.loadedIframe = false;
|
this.loadedIframe = false;
|
||||||
let iframe = document.getElementById('app_iframe') as HTMLIFrameElement;
|
const iframe = document.getElementById('app_iframe') as HTMLIFrameElement;
|
||||||
//load resource
|
//load resource
|
||||||
iframe.src = this.sidebar.currentModule.main;
|
iframe.src = this.sidebar.currentModule.main;
|
||||||
//loading finish
|
//loading finish
|
||||||
@ -65,7 +69,7 @@ export class PagesComponent implements OnInit {
|
|||||||
this.remoteService.switchDataSource();
|
this.remoteService.switchDataSource();
|
||||||
};
|
};
|
||||||
|
|
||||||
updateState = debounce(async () => {
|
updateState = async () => {
|
||||||
if (!this.isRemote && localStorage.getItem(IS_SHOW_REMOTE_SERVER_NOTIFICATION) !== 'false') {
|
if (!this.isRemote && localStorage.getItem(IS_SHOW_REMOTE_SERVER_NOTIFICATION) !== 'false') {
|
||||||
const [isSuccess] = await this.remoteService.pingRmoteServerUrl();
|
const [isSuccess] = await this.remoteService.pingRmoteServerUrl();
|
||||||
this.isShow = isSuccess;
|
this.isShow = isSuccess;
|
||||||
@ -73,7 +77,7 @@ export class PagesComponent implements OnInit {
|
|||||||
// if (!) {
|
// if (!) {
|
||||||
// this.isClose = false;
|
// this.isClose = false;
|
||||||
// }
|
// }
|
||||||
}, 500);
|
};
|
||||||
|
|
||||||
private watchRemoteServerChange() {
|
private watchRemoteServerChange() {
|
||||||
this.messageService
|
this.messageService
|
||||||
@ -82,7 +86,7 @@ export class PagesComponent implements OnInit {
|
|||||||
.subscribe((inArg: Message) => {
|
.subscribe((inArg: Message) => {
|
||||||
switch (inArg.type) {
|
switch (inArg.type) {
|
||||||
case 'onDataSourceChange': {
|
case 'onDataSourceChange': {
|
||||||
this.updateState();
|
this.rawChange$.next(inArg.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export { DataStorageComponent } from './data-storage.component';
|
export { DataStorageComponent } from './data-storage.component';
|
||||||
export { LanguageSwticherComponent } from './language-swtcher.componet';
|
export { LanguageSwticherComponent } from './language-swtcher.component';
|
||||||
export { AboutComponent } from './about.component';
|
export { AboutComponent } from './about.component';
|
||||||
|
@ -3,10 +3,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|||||||
import { SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import { FlatTreeControl } from '@angular/cdk/tree';
|
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||||
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
|
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
|
||||||
import { debounce, cloneDeep } from 'lodash';
|
|
||||||
import { eoapiSettings } from './eoapi-settings/';
|
import { eoapiSettings } from './eoapi-settings/';
|
||||||
import { Message, MessageService } from '../../../shared/services/message';
|
import { Message, MessageService } from '../../../shared/services/message';
|
||||||
import { Subject, takeUntil } from 'rxjs';
|
import { Subject, takeUntil, debounceTime } from 'rxjs';
|
||||||
import { NzMessageService } from 'ng-zorro-antd/message';
|
import { NzMessageService } from 'ng-zorro-antd/message';
|
||||||
import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service';
|
import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@ -48,11 +47,11 @@ export class SettingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
@Output() isShowModalChange = new EventEmitter<any>();
|
@Output() isShowModalChange = new EventEmitter<any>();
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
/** 是否远程数据源 */
|
/** Whether the remote data source */
|
||||||
get isRemote() {
|
get isRemote() {
|
||||||
return this.remoteService.isRemote;
|
return this.remoteService.isRemote;
|
||||||
}
|
}
|
||||||
/** 当前数据源对应的文本 */
|
/** The text corresponding to the current data source */
|
||||||
get dataSourceText() {
|
get dataSourceText() {
|
||||||
return this.remoteService.dataSourceText;
|
return this.remoteService.dataSourceText;
|
||||||
}
|
}
|
||||||
@ -94,7 +93,7 @@ export class SettingComponent implements OnInit {
|
|||||||
get settings() {
|
get settings() {
|
||||||
return this.$settings;
|
return this.$settings;
|
||||||
}
|
}
|
||||||
treeNodes = [
|
readonly treeNodes = [
|
||||||
{
|
{
|
||||||
name: $localize`:@@DataSource:Data Storage`,
|
name: $localize`:@@DataSource:Data Storage`,
|
||||||
moduleID: 'eoapi-common',
|
moduleID: 'eoapi-common',
|
||||||
@ -159,7 +158,7 @@ export class SettingComponent implements OnInit {
|
|||||||
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
|
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换数据源
|
* switch data source
|
||||||
*/
|
*/
|
||||||
switchDataSource() {
|
switchDataSource() {
|
||||||
this.switchDataSourceLoading = true;
|
this.switchDataSourceLoading = true;
|
||||||
@ -170,16 +169,16 @@ export class SettingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置数据
|
* set data
|
||||||
*
|
*
|
||||||
* @param properties
|
* @param properties
|
||||||
*/
|
*/
|
||||||
private setSettingsModel(properties, controls) {
|
private setSettingsModel(properties, controls) {
|
||||||
// 平级配置对象
|
// Flat configuration object
|
||||||
Object.keys(properties).forEach((fieldKey) => {
|
Object.keys(properties).forEach((fieldKey) => {
|
||||||
const props = properties[fieldKey];
|
const props = properties[fieldKey];
|
||||||
this.settings[fieldKey] = this.localSettings?.[fieldKey] ?? props.default;
|
this.settings[fieldKey] = this.localSettings?.[fieldKey] ?? props.default;
|
||||||
// 可扩展加入更多默认校验
|
// Extensible to add more default checks
|
||||||
if (props.required) {
|
if (props.required) {
|
||||||
controls[fieldKey] = [null, [Validators.required]];
|
controls[fieldKey] = [null, [Validators.required]];
|
||||||
} else {
|
} else {
|
||||||
@ -207,7 +206,7 @@ export class SettingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据key路径获取对应的配置的值
|
* Get the value of the corresponding configuration according to the key path
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* @returns
|
* @returns
|
||||||
@ -216,7 +215,7 @@ export class SettingComponent implements OnInit {
|
|||||||
// return key.split('.').reduce((p, k) => p?.[k], this.nestedSettings);
|
// return key.split('.').reduce((p, k) => p?.[k], this.nestedSettings);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取模块的标题
|
* Get the title of the module
|
||||||
*
|
*
|
||||||
* @param module
|
* @param module
|
||||||
* @returns
|
* @returns
|
||||||
@ -234,15 +233,15 @@ export class SettingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析所有模块的配置信息
|
* Parse the configuration information of all modules
|
||||||
*/
|
*/
|
||||||
private init() {
|
private init() {
|
||||||
// if (!window.eo && !window.eo?.getFeature) {
|
// if (!window.eo && !window.eo?.getFeature) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// ! this.isVisible = true;
|
// ! this.isVisible = true;
|
||||||
// 获取本地设置
|
// Get local settings
|
||||||
this.settings = this.localSettings = JSON.parse(localStorage.getItem('localSettings') || '{}');
|
this.settings = this.localSettings = this.remoteService.getSettings();
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.getConfiguration = this.remoteService.getConfiguration;
|
window.getConfiguration = this.remoteService.getConfiguration;
|
||||||
console.log('localSettings', this.localSettings);
|
console.log('localSettings', this.localSettings);
|
||||||
@ -251,9 +250,9 @@ export class SettingComponent implements OnInit {
|
|||||||
// const extensitonConfigurations = [...modules.values()].filter((n) => n.contributes?.configuration);
|
// const extensitonConfigurations = [...modules.values()].filter((n) => n.contributes?.configuration);
|
||||||
const extensitonConfigurations = [...modules.values()].filter((n) => n.features?.configuration);
|
const extensitonConfigurations = [...modules.values()].filter((n) => n.features?.configuration);
|
||||||
const controls = {};
|
const controls = {};
|
||||||
// 所有设置
|
// All settings
|
||||||
const allSettings = cloneDeep([eoapiSettings['eoapi-extensions']]);
|
const allSettings = structuredClone([eoapiSettings['eoapi-extensions']]);
|
||||||
// 所有配置
|
// All configure
|
||||||
const allConfiguration = allSettings.map((n) => {
|
const allConfiguration = allSettings.map((n) => {
|
||||||
const configuration = n.features?.configuration || n.contributes?.configuration;
|
const configuration = n.features?.configuration || n.contributes?.configuration;
|
||||||
if (Array.isArray(configuration)) {
|
if (Array.isArray(configuration)) {
|
||||||
@ -275,14 +274,14 @@ export class SettingComponent implements OnInit {
|
|||||||
extensionsConfiguration.push(configuration);
|
extensionsConfiguration.push(configuration);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 给插件的属性前面追加模块ID
|
// Appends the module ID to the plug-in property
|
||||||
const appendModuleID = (properties, moduleID) =>
|
const appendModuleID = (properties, moduleID) =>
|
||||||
Object.keys(properties).reduce((prev, key) => {
|
Object.keys(properties).reduce((prev, key) => {
|
||||||
prev[`${moduleID}.${key}`] = properties[key];
|
prev[`${moduleID}.${key}`] = properties[key];
|
||||||
return prev;
|
return prev;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
/** 根据configuration配置生成settings model */
|
/** Generate settings model based on configuration configuration */
|
||||||
allConfiguration.forEach((item) => {
|
allConfiguration.forEach((item) => {
|
||||||
if (Array.isArray(item)) {
|
if (Array.isArray(item)) {
|
||||||
item.forEach((n) => {
|
item.forEach((n) => {
|
||||||
@ -295,7 +294,7 @@ export class SettingComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
type Configuration = typeof allConfiguration[number] | Array<typeof allConfiguration[number]>;
|
type Configuration = typeof allConfiguration[number] | Array<typeof allConfiguration[number]>;
|
||||||
// 递归生成设置树
|
// Recursively generate the setup tree
|
||||||
const generateTreeData = (configurations: Configuration = []) =>
|
const generateTreeData = (configurations: Configuration = []) =>
|
||||||
[].concat(configurations).reduce<TreeNode[]>((prev, curr) => {
|
[].concat(configurations).reduce<TreeNode[]>((prev, curr) => {
|
||||||
if (Array.isArray(curr)) {
|
if (Array.isArray(curr)) {
|
||||||
@ -307,8 +306,8 @@ export class SettingComponent implements OnInit {
|
|||||||
};
|
};
|
||||||
return prev.concat(treeItem);
|
return prev.concat(treeItem);
|
||||||
}, []);
|
}, []);
|
||||||
// 所有设置项
|
// All settings
|
||||||
const treeData = cloneDeep(this.treeNodes);
|
const treeData = structuredClone(this.treeNodes);
|
||||||
const extensions = treeData.find((n) => n.moduleID === 'eoapi-extensions');
|
const extensions = treeData.find((n) => n.moduleID === 'eoapi-extensions');
|
||||||
const extensionConfiguration = allSettings[0].features?.configuration || allSettings[0].contributes?.configuration;
|
const extensionConfiguration = allSettings[0].features?.configuration || allSettings[0].contributes?.configuration;
|
||||||
extensions.children = generateTreeData(extensionConfiguration);
|
extensions.children = generateTreeData(extensionConfiguration);
|
||||||
@ -316,8 +315,8 @@ export class SettingComponent implements OnInit {
|
|||||||
this.dataSource.setData(treeData);
|
this.dataSource.setData(treeData);
|
||||||
this.treeControl.expandAll();
|
this.treeControl.expandAll();
|
||||||
this.validateForm = this.fb.group(controls);
|
this.validateForm = this.fb.group(controls);
|
||||||
this.validateForm.valueChanges.subscribe(debounce(this.handleSave.bind(this), 300));
|
this.validateForm.valueChanges.pipe(debounceTime(300)).subscribe(this.handleSave);
|
||||||
// 默认选中第一项
|
// The first item is selected by default
|
||||||
this.selectModule(this.treeControl.dataNodes.at(0));
|
this.selectModule(this.treeControl.dataNodes.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +330,7 @@ export class SettingComponent implements OnInit {
|
|||||||
this.isShowModal = true;
|
this.isShowModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSave(): void {
|
handleSave = () => {
|
||||||
// for (const i in this.validateForm.controls) {
|
// for (const i in this.validateForm.controls) {
|
||||||
// if (this.validateForm.controls.hasOwnProperty(i)) {
|
// if (this.validateForm.controls.hasOwnProperty(i)) {
|
||||||
// this.validateForm.controls[i].markAsDirty();
|
// this.validateForm.controls[i].markAsDirty();
|
||||||
@ -343,7 +342,7 @@ export class SettingComponent implements OnInit {
|
|||||||
// }
|
// }
|
||||||
localStorage.setItem('localSettings', JSON.stringify(this.settings));
|
localStorage.setItem('localSettings', JSON.stringify(this.settings));
|
||||||
window.eo?.saveSettings?.({ ...this.settings });
|
window.eo?.saveSettings?.({ ...this.settings });
|
||||||
}
|
};
|
||||||
|
|
||||||
async handleCancel() {
|
async handleCancel() {
|
||||||
try {
|
try {
|
||||||
@ -351,15 +350,11 @@ export class SettingComponent implements OnInit {
|
|||||||
this.remoteServerUrl !== this.settings['eoapi-common.remoteServer.url'] ||
|
this.remoteServerUrl !== this.settings['eoapi-common.remoteServer.url'] ||
|
||||||
this.remoteServerToken !== this.settings['eoapi-common.remoteServer.token'] ||
|
this.remoteServerToken !== this.settings['eoapi-common.remoteServer.token'] ||
|
||||||
this.oldDataStorage !== this.settings['eoapi-common.dataStorage'];
|
this.oldDataStorage !== this.settings['eoapi-common.dataStorage'];
|
||||||
console.log(
|
|
||||||
'isUpdateRemoteInfo',
|
|
||||||
isUpdateRemoteInfo,
|
|
||||||
this.settings,
|
|
||||||
this.remoteServerUrl,
|
|
||||||
this.remoteServerToken
|
|
||||||
);
|
|
||||||
if (isUpdateRemoteInfo) {
|
if (isUpdateRemoteInfo) {
|
||||||
this.message.success('你已修改数据源相关信息,页面将在2秒后刷新...');
|
this.message.success(
|
||||||
|
'You have modified the data source related information, the page will refresh in 2 seconds...'
|
||||||
|
);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.remoteService.switchDataSource();
|
this.remoteService.switchDataSource();
|
||||||
this.remoteService.refreshComponent();
|
this.remoteService.refreshComponent();
|
||||||
|
@ -80,7 +80,7 @@ export class RemoteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试远程服务器地址是否可用
|
* Test if remote server address is available
|
||||||
*/
|
*/
|
||||||
async pingRmoteServerUrl(): Promise<[boolean, any]> {
|
async pingRmoteServerUrl(): Promise<[boolean, any]> {
|
||||||
const { url: remoteUrl, token } = window.eo?.getModuleSettings('eoapi-common.remoteServer') || {};
|
const { url: remoteUrl, token } = window.eo?.getModuleSettings('eoapi-common.remoteServer') || {};
|
||||||
@ -126,7 +126,7 @@ export class RemoteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据key路径获取对应的配置的值
|
* Get the value of the corresponding configuration according to the key path
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* @returns
|
* @returns
|
||||||
|
@ -110,7 +110,7 @@ export interface ApiTestHistoryResponse {
|
|||||||
body: string;
|
body: string;
|
||||||
contentType: string;
|
contentType: string;
|
||||||
responseType: 'text' | 'longText' | 'stream';
|
responseType: 'text' | 'longText' | 'stream';
|
||||||
blobFileName?:string;
|
blobFileName?: string;
|
||||||
responseLength: number;
|
responseLength: number;
|
||||||
testDeny: string;
|
testDeny: string;
|
||||||
/**
|
/**
|
||||||
|
@ -8064,7 +8064,7 @@ lodash.without@~4.4.0:
|
|||||||
resolved "https://registry.npmmirror.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
|
resolved "https://registry.npmmirror.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
|
||||||
integrity sha512-M3MefBwfDhgKgINVuBJCO1YR3+gf6s9HNJsIiZ/Ru77Ws6uTb9eBuvrkpzO+9iLoAaRodGuq7tyrPCx+74QYGQ==
|
integrity sha512-M3MefBwfDhgKgINVuBJCO1YR3+gf6s9HNJsIiZ/Ru77Ws6uTb9eBuvrkpzO+9iLoAaRodGuq7tyrPCx+74QYGQ==
|
||||||
|
|
||||||
lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21:
|
lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
Loading…
Reference in New Issue
Block a user