From 0cb7ff96863bf8cb6a7db07f2178a882db01b315 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sat, 5 Nov 2022 08:38:44 +0300 Subject: [PATCH 01/16] =?UTF-8?q?=D0=9D=D0=B5=20=D0=BE=D1=82=D0=BA=D1=80?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D1=83=D0=BB=D1=8C=20=D1=84=D0=BE=D1=80=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index bd5cc0f..40bfbaa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -30,7 +30,7 @@ export function activate(context: vscode.ExtensionContext) { OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openForm', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Forms/' + node.label + '/Ext/Form/Module.bsl'; + const filePath = rootPath + '/' + node.path + '/Ext/Form/Module.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openModule', (node: TreeItem) => { From 4eb85f5136275622dd58cf4b036db4d540b88a2c Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Sat, 5 Nov 2022 09:31:04 +0300 Subject: [PATCH 02/16] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D0=BF=D1=83?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D1=8F=20=D1=80=D0=B5?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a81239e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: Publish package to VSCode Marketplace + +on: + release: + types: [published] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: '16' + - run: npm install + - name: Build package + run: npx vsce package + - name: Upload vsix to release + uses: AButler/upload-release-assets@v1.0 + with: + files: '*.vsix' + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: lannonbr/vsce-action@master + if: github.event.release.prerelease == false + with: + args: "publish -p $VSCE_TOKEN" + env: + VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }} From 300f8efb1eede4ed43182234126f05411a9d5f37 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Sat, 5 Nov 2022 11:22:06 +0300 Subject: [PATCH 03/16] =?UTF-8?q?=D0=A3=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20vsce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a81239e..3464ffd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ jobs: with: node-version: '16' - run: npm install + - run: npm install -g vsce - name: Build package run: npx vsce package - name: Upload vsix to release From 28060b38dd149a7c0af1238df0695f5b4975b865 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sat, 5 Nov 2022 12:21:02 +0300 Subject: [PATCH 04/16] =?UTF-8?q?=D0=97=D0=B0=D0=BA=D0=BE=D0=BD=D1=87?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BC=D0=B5=D1=82=D0=B0=D0=B4=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=B2=D0=B5=D1=80=D1=85=D0=BD=D0=B5=D0=B3=D0=BE?= =?UTF-8?q?=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/dark/accountingFlag.svg | 4 + resources/dark/extDimensionAccountingFlag.svg | 4 + resources/light/accountingFlag.svg | 4 + .../light/extDimensionAccountingFlag.svg | 4 + src/metadataView.ts | 123 ++++++++++++++++-- 5 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 resources/dark/accountingFlag.svg create mode 100644 resources/dark/extDimensionAccountingFlag.svg create mode 100644 resources/light/accountingFlag.svg create mode 100644 resources/light/extDimensionAccountingFlag.svg diff --git a/resources/dark/accountingFlag.svg b/resources/dark/accountingFlag.svg new file mode 100644 index 0000000..99c85c2 --- /dev/null +++ b/resources/dark/accountingFlag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/dark/extDimensionAccountingFlag.svg b/resources/dark/extDimensionAccountingFlag.svg new file mode 100644 index 0000000..8aea1c0 --- /dev/null +++ b/resources/dark/extDimensionAccountingFlag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/light/accountingFlag.svg b/resources/light/accountingFlag.svg new file mode 100644 index 0000000..651cdfa --- /dev/null +++ b/resources/light/accountingFlag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/light/extDimensionAccountingFlag.svg b/resources/light/extDimensionAccountingFlag.svg new file mode 100644 index 0000000..b034b05 --- /dev/null +++ b/resources/light/extDimensionAccountingFlag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/metadataView.ts b/src/metadataView.ts index 5bf3d14..c94ff21 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -23,8 +23,15 @@ interface MetadataObjects { report: TreeItem[], dataProcessor: TreeItem[], сhartOfCharacteristicTypes: TreeItem[], + chartOfAccounts: TreeItem[], + chartOfCalculationTypes: TreeItem[], informationRegister: TreeItem[], accumulationRegister: TreeItem[], + accountingRegister: TreeItem[], + calculationRegister: TreeItem[], + businessProcess: TreeItem[], + task: TreeItem[], + externalDataSource: TreeItem[], } type IconType = 'common' | 'subsystem' | 'commonModule' | 'sessionParameter' | 'role' | 'attribute' | @@ -32,7 +39,8 @@ type IconType = 'common' | 'subsystem' | 'commonModule' | 'sessionParameter' | ' 'dataProcessor' | 'chartsOfCharacteristicType' | 'chartsOfAccount' | 'chartsOfCalculationType' | 'informationRegister' | 'accumulationRegister' | 'tabularSection' | 'form' | 'command' | 'template' | 'dimension' | 'resource' | 'column' | 'task' | 'businessProcess' | 'externalDataSource' | - 'accountingRegister' | 'calculationRegister' | 'filterCriteria' | 'eventSubscription' | 'scheduledJob'; + 'accountingRegister' | 'calculationRegister' | 'filterCriteria' | 'eventSubscription' | 'scheduledJob' | + 'accountingFlag' | 'extDimensionAccountingFlag'; interface TreeItemParams { icon?: IconType, @@ -175,13 +183,13 @@ function CreateTreeElements(metadataFile: MetadataFile) { previous.constant.push(GetTreeItem(current, { icon: 'constant', context: 'valueManager_and_manager' })); } if (current.$.name.startsWith('Catalog.')) { previous.catalog.push(GetTreeItem(current, { - icon: 'catalog', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult ) })); + icon: 'catalog', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('Document.')) { previous.document.push(GetTreeItem(current, { - icon: 'document', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult ) })); + icon: 'document', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('DocumentJournal.')) { previous.documentJournal.push(GetTreeItem(current, { - icon: 'documentJournal', context: 'manager', children: FillDocumentJournalItemsByMetadata(current, attributeReduceResult ) })); + icon: 'documentJournal', context: 'manager', children: FillDocumentJournalItemsByMetadata(current, attributeReduceResult) })); } if (current.$.name.startsWith('Enum.')) { previous.enum.push(GetTreeItem(current, { icon: 'enum', context: 'manager', children: FillEnumItemsByMetadata(current, attributeReduceResult) })); @@ -194,12 +202,33 @@ function CreateTreeElements(metadataFile: MetadataFile) { } else if (current.$.name.startsWith('ChartOfCharacteristicTypes.')) { previous.сhartOfCharacteristicTypes.push(GetTreeItem(current, { icon: 'chartsOfCharacteristicType', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); - } else if (current.$.name.startsWith('InformationRegister')) { + } else if (current.$.name.startsWith('ChartOfAccounts.')) { + previous.chartOfAccounts.push(GetTreeItem(current, { + icon: 'chartsOfAccount', context: 'object_and_manager', children: FillChartOfAccountsItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('ChartOfCalculationTypes.')) { + previous.chartOfCalculationTypes.push(GetTreeItem(current, { + icon: 'chartsOfCalculationType', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('InformationRegister.')) { previous.informationRegister.push(GetTreeItem(current, { - icon: 'informationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult ) })); - } else if (current.$.name.startsWith('AccumulationRegister')) { + icon: 'informationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('AccumulationRegister.')) { previous.accumulationRegister.push(GetTreeItem(current, { - icon: 'accumulationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult ) })); + icon: 'accumulationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('AccountingRegister.')) { + previous.accountingRegister.push(GetTreeItem(current, { + icon: 'accountingRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('CalculationRegister.')) { + previous.calculationRegister.push(GetTreeItem(current, { + icon: 'calculationRegister', context: 'recordset_and_manager', children: FillCalculationRegisterItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('BusinessProcess.')) { + previous.businessProcess.push(GetTreeItem(current, { + icon: 'businessProcess', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('Task.')) { + previous.task.push(GetTreeItem(current, { + icon: 'task', context: 'object_and_manager', children: FillTaskItemsByMetadata(current, attributeReduceResult) })); + } else if (current.$.name.startsWith('ExternalDataSource.')) { + previous.externalDataSource.push(GetTreeItem(current, { + icon: 'externalDataSource', children: FillExternalDataSourceItemsByMetadata(current, attributeReduceResult) })); } return previous; @@ -217,8 +246,15 @@ function CreateTreeElements(metadataFile: MetadataFile) { report: [], dataProcessor: [], сhartOfCharacteristicTypes: [], + chartOfAccounts: [], + chartOfCalculationTypes: [], informationRegister: [], - accumulationRegister: [] + accumulationRegister: [], + accountingRegister: [], + calculationRegister: [], + businessProcess: [], + task: [], + externalDataSource: [], }); SearchTree(tree[0], 'commonModules')!.children = reduceResult.commonModule; @@ -237,8 +273,15 @@ function CreateTreeElements(metadataFile: MetadataFile) { SearchTree(tree[0], 'reports')!.children = reduceResult.report; SearchTree(tree[0], 'dataProcessors')!.children = reduceResult.dataProcessor; SearchTree(tree[0], 'chartsOfCharacteristicTypes')!.children = reduceResult.сhartOfCharacteristicTypes; + SearchTree(tree[0], 'chartsOfAccounts')!.children = reduceResult.chartOfAccounts; + SearchTree(tree[0], 'chartsOfCalculationTypes')!.children = reduceResult.chartOfCalculationTypes; SearchTree(tree[0], 'informationRegisters')!.children = reduceResult.informationRegister; SearchTree(tree[0], 'accumulationRegisters')!.children = reduceResult.accumulationRegister; + SearchTree(tree[0], 'accountingRegisters')!.children = reduceResult.accountingRegister; + SearchTree(tree[0], 'calculationRegisters')!.children = reduceResult.calculationRegister; + SearchTree(tree[0], 'businessProcesses')!.children = reduceResult.businessProcess; + SearchTree(tree[0], 'tasks')!.children = reduceResult.task; + SearchTree(tree[0], 'externalDataSources')!.children = reduceResult.externalDataSource; console.timeEnd('reduce'); } @@ -291,6 +334,27 @@ function FillEnumItemsByMetadata(versionMetadata: VersionMetadata, objectData: M return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; } +function FillChartOfAccountsItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { + const accountingFlags = (versionMetadata + .Metadata ?? []) + .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.AccountingFlag.')) + .map(m => GetTreeItem(m, { icon: 'accountingFlag' })); + + const extDimensionAccountingFlag = (versionMetadata + .Metadata ?? []) + .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.ExtDimensionAccountingFlag.')) + .map(m => GetTreeItem(m, { icon: 'extDimensionAccountingFlag' })); + + const items = [ + GetTreeItem({ $: { id: '', name: 'Признаки учета'}}, { icon: 'accountingFlag', children: accountingFlags.length === 0 ? undefined : accountingFlags }), + GetTreeItem({ $: { id: '', name: 'Признаки учета субконто'}}, { + icon: 'extDimensionAccountingFlag', children: extDimensionAccountingFlag.length === 0 ? undefined : extDimensionAccountingFlag }), + ]; + + return [ ...items, ...FillObjectItemsByMetadata(versionMetadata, objectData) ] + .sort((x, y) => { return x.label == "Реквизиты" ? -1 : y.label == "Реквизиты" ? 1 : 0; }); +} + function FillRegisterItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const dimensions = (versionMetadata .Metadata ?? []) @@ -316,6 +380,36 @@ function FillRegisterItemsByMetadata(versionMetadata: VersionMetadata, objectDat return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; } +function FillCalculationRegisterItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { + const items: TreeItem[] = [ + // TODO: Перерасчеты + ]; + + return [ ...items, ...FillRegisterItemsByMetadata(versionMetadata, objectData) ]; +} + +function FillTaskItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { + const attributes = (versionMetadata + .Metadata ?? []) + .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.AddressingAttribute.')) + .map(m => GetTreeItem(m, { icon: 'attribute' })); + + const items = [ + GetTreeItem({ $: { id: '', name: 'Реквизиты адресации'}}, { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), + ]; + + return [ ...items, ...FillObjectItemsByMetadata(versionMetadata, objectData) ] + .sort((x, y) => { return x.label == "Реквизиты" ? -1 : y.label == "Реквизиты" ? 1 : 0; }); +} + +function FillExternalDataSourceItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { + const items: TreeItem[] = [ + // TODO: + ]; + + return items; +} + function FillCommonItems(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const commands = (versionMetadata .Metadata ?? []) @@ -359,6 +453,7 @@ function SearchTree(element: TreeItem, matchingId: string): TreeItem | null { return null; } +// TODO: Ужасная функция!!!1 Первая очередь на рефакторинг! function CreatePath(name: string): string { return name .replace('CommonModule.', 'CommonModules/') @@ -370,8 +465,16 @@ function CreatePath(name: string): string { .replace('Enum.', 'Enums/') .replace('Report.', 'Reports/') .replace('DataProcessor.', 'DataProcessors/') + .replace('ChartOfCharacteristicTypes.', 'ChartsOfCharacteristicTypes/') + .replace('ChartOfAccounts.', 'ChartsOfAccounts/') + .replace('ChartOfCalculationTypes.', 'ChartsOfCalculationTypes/') .replace('InformationRegister.', 'InformationRegisters/') - .replace('AccumulationRegister.', 'AccumulationRegisters/'); + .replace('AccumulationRegister.', 'AccumulationRegisters/') + .replace('AccountingRegister.', 'AccountingRegisters/') + .replace('CalculationRegister.', 'CalculationRegisters/') + .replace('BusinessProcess.', 'BusinessProcesses/') + .replace('Task.', 'Tasks/') + .replace('ExternalDataSource.', 'ExternalDataSources/'); } function NodeWithIdTreeDataProvider(): vscode.TreeDataProvider { From 7aa09dd2c519c341b3a927c96990209aab125127 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sat, 5 Nov 2022 13:26:27 +0300 Subject: [PATCH 05/16] =?UTF-8?q?=D0=9F=D1=83=D0=BD=D0=BA=D1=82=20=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=BA=D1=82=D0=BD=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=B8=20=D1=87=D1=82=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20XML?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 9 ++++++++ package.nls.json | 3 ++- package.nls.ru.json | 3 ++- src/metadataInterfaces.ts | 2 +- src/metadataView.ts | 37 +++++++++++++++++++++++++++------ src/predefinedDataInterfaces.ts | 15 +++++++++++++ src/predefinedDataPanel.ts | 8 +++++++ 7 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/predefinedDataInterfaces.ts create mode 100644 src/predefinedDataPanel.ts diff --git a/package.json b/package.json index 9a819a8..8940bfb 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,10 @@ { "command": "metadataViewer.openXml", "title": "%1c-metadata-viewer.openXml.title%" + }, + { + "command": "metadataViewer.openPredefinedData", + "title": "%1c-metadata-viewer.openPredefinedData.title%" } ], "menus": { @@ -135,6 +139,11 @@ "command": "metadataViewer.openXml", "group": "xml", "when": "viewItem" + }, + { + "command": "metadataViewer.openPredefinedData", + "group": "bsl", + "when": "viewItem =~ /predefined/" } ] }, diff --git a/package.nls.json b/package.nls.json index 6b9e0b3..f9a469a 100644 --- a/package.nls.json +++ b/package.nls.json @@ -9,5 +9,6 @@ "1c-metadata-viewer.openCommandModule.title": "Open command module", "1c-metadata-viewer.openRecordSetModule.title": "Open record set module", "1c-metadata-viewer.openValueManagerModule.title": "Open value manager module", - "1c-metadata-viewer.openXml.title": "Open XML" + "1c-metadata-viewer.openXml.title": "Open XML", + "1c-metadata-viewer.openPredefinedData.title": "Open predefined data" } \ No newline at end of file diff --git a/package.nls.ru.json b/package.nls.ru.json index 42c893a..5eb9da3 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -9,5 +9,6 @@ "1c-metadata-viewer.openCommandModule.title": "Открыть модуль команды", "1c-metadata-viewer.openRecordSetModule.title": "Открыть модуль набора записей", "1c-metadata-viewer.openValueManagerModule.title": "Открыть модуль менеджера значения", - "1c-metadata-viewer.openXml.title": "Открыть XML" + "1c-metadata-viewer.openXml.title": "Открыть XML", + "1c-metadata-viewer.openPredefinedData.title": "Открыть предопределенные данные" } \ No newline at end of file diff --git a/src/metadataInterfaces.ts b/src/metadataInterfaces.ts index aa115bf..5f3f844 100644 --- a/src/metadataInterfaces.ts +++ b/src/metadataInterfaces.ts @@ -15,7 +15,7 @@ export interface VersionMetadata { Metadata?: ObjectMetadata[]; } -interface ObjectParams { +export interface ObjectParams { name: string; id: string; configVersion: string; diff --git a/src/metadataView.ts b/src/metadataView.ts index c94ff21..22b2c91 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -1,8 +1,11 @@ +import * as fs from 'fs'; import * as vscode from 'vscode'; import * as xml2js from 'xml2js'; import { posix } from 'path'; import * as path from 'path'; -import { MetadataFile, ObjectMetadata, VersionMetadata } from './metadataInterfaces'; +import { MetadataFile, ObjectMetadata, ObjectParams, VersionMetadata } from './metadataInterfaces'; +import { PredefinedDataFile } from './predefinedDataInterfaces'; +import { PredefinedDataPanel } from './predefinedDataPanel'; interface MetadataDictionaries { form: { [key: string]: TreeItem[] }, @@ -76,7 +79,29 @@ export class MetadataView { const folderUri = folder.uri; LoadAndParseConfigurationXml(folderUri); }); - } + + vscode.commands.registerCommand('metadataViewer.openPredefinedData', (item) => this.openPredefinedData(context, item)); + } + + private openPredefinedData(context: vscode.ExtensionContext, item: TreeItem): void { + const rootPath = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) + ? vscode.workspace.workspaceFolders[0].uri : undefined; + + if (rootPath) { + const fileName = posix.join(rootPath.fsPath, item.path!, 'Ext/Predefined.xml'); + if (!fs.existsSync(fileName)) { + PredefinedDataPanel.show(context.extensionUri, { Item: [] }); + } else { + vscode.workspace.fs.readFile(rootPath.with({ path: fileName })) + .then(configXml => { + xml2js.parseString(configXml, (err, result) => { + const typedResult = result as PredefinedDataFile; + PredefinedDataPanel.show(context.extensionUri, typedResult.PredefinedData); + }); + }); + } + } + } } const tree: TreeItem[] = [ @@ -183,7 +208,7 @@ function CreateTreeElements(metadataFile: MetadataFile) { previous.constant.push(GetTreeItem(current, { icon: 'constant', context: 'valueManager_and_manager' })); } if (current.$.name.startsWith('Catalog.')) { previous.catalog.push(GetTreeItem(current, { - icon: 'catalog', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + icon: 'catalog', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('Document.')) { previous.document.push(GetTreeItem(current, { icon: 'document', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); @@ -201,13 +226,13 @@ function CreateTreeElements(metadataFile: MetadataFile) { icon: 'dataProcessor', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('ChartOfCharacteristicTypes.')) { previous.сhartOfCharacteristicTypes.push(GetTreeItem(current, { - icon: 'chartsOfCharacteristicType', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + icon: 'chartsOfCharacteristicType', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('ChartOfAccounts.')) { previous.chartOfAccounts.push(GetTreeItem(current, { - icon: 'chartsOfAccount', context: 'object_and_manager', children: FillChartOfAccountsItemsByMetadata(current, attributeReduceResult) })); + icon: 'chartsOfAccount', context: 'object_and_manager_and_predefined', children: FillChartOfAccountsItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('ChartOfCalculationTypes.')) { previous.chartOfCalculationTypes.push(GetTreeItem(current, { - icon: 'chartsOfCalculationType', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + icon: 'chartsOfCalculationType', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); } else if (current.$.name.startsWith('InformationRegister.')) { previous.informationRegister.push(GetTreeItem(current, { icon: 'informationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); diff --git a/src/predefinedDataInterfaces.ts b/src/predefinedDataInterfaces.ts new file mode 100644 index 0000000..c1f60e1 --- /dev/null +++ b/src/predefinedDataInterfaces.ts @@ -0,0 +1,15 @@ +export interface PredefinedDataFile { + PredefinedData: PredefinedData; +} + +export interface PredefinedData { + Item: PredefinedDataItem[]; +} + +interface PredefinedDataItem { + ChildItems: PredefinedData[]; + Code: string[]; + Description: string[]; + IsFolder: string[]; + Name: string[]; +} \ No newline at end of file diff --git a/src/predefinedDataPanel.ts b/src/predefinedDataPanel.ts new file mode 100644 index 0000000..74523bd --- /dev/null +++ b/src/predefinedDataPanel.ts @@ -0,0 +1,8 @@ +import * as vscode from 'vscode'; +import { PredefinedData } from './predefinedDataInterfaces'; + +export class PredefinedDataPanel { + public static show(extensionUri: vscode.Uri, data: PredefinedData) { + console.log(JSON.stringify(data)); + } +} \ No newline at end of file From 672ff4491ee835d0fd722b746e6ee3667c9b47cd Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sat, 5 Nov 2022 17:20:14 +0300 Subject: [PATCH 06/16] =?UTF-8?q?=D0=92=20=D0=BF=D1=80=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D0=BA=D1=88=D0=B5=D0=BD!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/dark/folder.svg | 4 ++ resources/light/folder.svg | 4 ++ src/predefinedDataInterfaces.ts | 2 +- src/predefinedDataPanel.ts | 79 +++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 resources/dark/folder.svg create mode 100644 resources/light/folder.svg diff --git a/resources/dark/folder.svg b/resources/dark/folder.svg new file mode 100644 index 0000000..3bf26ad --- /dev/null +++ b/resources/dark/folder.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/light/folder.svg b/resources/light/folder.svg new file mode 100644 index 0000000..5f1638b --- /dev/null +++ b/resources/light/folder.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/predefinedDataInterfaces.ts b/src/predefinedDataInterfaces.ts index c1f60e1..2a86da9 100644 --- a/src/predefinedDataInterfaces.ts +++ b/src/predefinedDataInterfaces.ts @@ -6,7 +6,7 @@ export interface PredefinedData { Item: PredefinedDataItem[]; } -interface PredefinedDataItem { +export interface PredefinedDataItem { ChildItems: PredefinedData[]; Code: string[]; Description: string[]; diff --git a/src/predefinedDataPanel.ts b/src/predefinedDataPanel.ts index 74523bd..ed3e984 100644 --- a/src/predefinedDataPanel.ts +++ b/src/predefinedDataPanel.ts @@ -1,8 +1,79 @@ import * as vscode from 'vscode'; -import { PredefinedData } from './predefinedDataInterfaces'; +import { PredefinedData, PredefinedDataItem } from './predefinedDataInterfaces'; export class PredefinedDataPanel { - public static show(extensionUri: vscode.Uri, data: PredefinedData) { - console.log(JSON.stringify(data)); + public static readonly viewType = 'metadataViewer.predefinedPanel'; + + public static show(extensionUri: vscode.Uri, data: PredefinedData) { + const column = vscode.window.activeTextEditor + ? vscode.window.activeTextEditor.viewColumn + : undefined; + + const panel = vscode.window.createWebviewPanel( + PredefinedDataPanel.viewType, + "Предопределенные элементы", + column || vscode.ViewColumn.One + ); + + panel.webview.html = this._getHtmlForWebview(panel.webview, extensionUri, data); } -} \ No newline at end of file + + private static _getHtmlForWebview(webview: vscode.Webview, extensionUri: vscode.Uri, data: PredefinedData) { + const styleUri = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, 'media', 'predefined', 'styles.css')); + + // TODO: иконка catalog.svg для других предопределенных элементов должна быть другой + const isDark = vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark; + + const rootImagePath = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, 'resources', isDark ? 'dark' : 'light', 'catalog.svg')); + const folderImagePath = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, 'resources', isDark ? 'dark' : 'light', 'folder.svg')); + const elementImagePath = webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, 'resources', isDark ? 'dark' : 'light', 'attribute.svg')); + + // TODO: разобраться с безопасностью ресурсов и переделать + return ` + + + + + + + + + + + + + + + + + + + + ${data.Item.map(i => CreateItem(i, [ folderImagePath, elementImagePath ], 1)).join('')} + +
ИмяКодНаименование
 Элементы
+ + `; + } +} + +function CreateItem(item: PredefinedDataItem, imageUri: vscode.Uri[], level: number): string { + return ` + ${(() => { + if (item.IsFolder[0] === 'true') { + return ``; + } else { + return ``; + } + })()} ${item.Name} + ${item.Code} + ${item.Description} + + ${(() => { + if (item.ChildItems) { + return item.ChildItems[0].Item.map(i => CreateItem(i, imageUri, level + 1)).join(''); + } + + return ''; + })()}`; +} From 63d61a17d9ba5e51d39274db44787811960f6fb1 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sat, 5 Nov 2022 17:33:32 +0300 Subject: [PATCH 07/16] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=200.?= =?UTF-8?q?0.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 13 +++++++++++++ README.md | 7 +++++++ package.json | 2 +- resources/screenshot.png | Bin 13238 -> 14362 bytes 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e718a64..1711a7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +### 0.0.5 + +* [new] Просмотр предопределенных элементов +* [new] Закончил метаданные верхнего уровня + * Планы счетов + * Планы видов расчета + * Регистры бухгалтерии + * Регистры расчета + * Бизнес-процессы + * Задачи + * Внешние источники данных +* [fix] Не открывается модуль формы + ### 0.0.4 * [new] Открытие XML diff --git a/README.md b/README.md index 5befb81..8775c5e 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,15 @@ * Отчеты * Обработки * Планы видов характеристик +* Планы счетов +* Планы видов расчета * Регистры сведений * Регистры накопления +* Регистры бухгалтерии +* Регистры расчета +* Бизнес-процессы +* Задачи +* Внешние источники данных ### Модули diff --git a/package.json b/package.json index 8940bfb..ac7542a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-1c-metadata-viewer", "displayName": "1C Metadata Viewer", "description": "Explore 1C:Enterprise 8 configuration in the usual way", - "version": "0.0.4", + "version": "0.0.5", "publisher": "zerobig", "license": "MIT", "engines": { diff --git a/resources/screenshot.png b/resources/screenshot.png index 051f73f6c4db4af549929e10d1993ee6660698fa..f5a026e4fe8c99837019df53d2c34269535baf14 100644 GIT binary patch literal 14362 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 ItZC5y0fkEy^Z)<= literal 13238 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 Date: Sun, 6 Nov 2022 00:02:09 +0300 Subject: [PATCH 08/16] =?UTF-8?q?=D0=9C=D1=83=D0=BB=D1=8C=D1=82=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/extension.ts | 25 +- src/metadataView.ts | 546 ++++++++++++++++++++++++++++++-------------- 3 files changed, 386 insertions(+), 186 deletions(-) diff --git a/package.json b/package.json index ac7542a..5a2ad22 100644 --- a/package.json +++ b/package.json @@ -165,6 +165,7 @@ "typescript": "^4.8.4" }, "dependencies": { + "fast-glob": "^3.2.12", "xml2js": "^0.4.23" } } diff --git a/src/extension.ts b/src/extension.ts index 40bfbaa..4d5279e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,52 +5,49 @@ import { MetadataView, TreeItem } from './metadataView'; import * as fs from 'fs'; export function activate(context: vscode.ExtensionContext) { - const rootPath = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) - ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined; - vscode.commands.registerCommand('metadataViewer.openAppModule', (node: TreeItem) => { - const filePath = rootPath + '/Ext/ManagedApplicationModule.bsl'; + const filePath = node.path + '/Ext/ManagedApplicationModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openSessionModule', (node: TreeItem) => { - const filePath = rootPath + '/Ext/SessionModule.bsl'; + const filePath = node.path + '/Ext/SessionModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openExternalConnectionModule', (node: TreeItem) => { // TODO: Имя модуля проверить. Может быть не верным. - const filePath = rootPath + '/Ext/ExternalConnectionModule.bsl'; + const filePath = node.path + '/Ext/ExternalConnectionModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openObjectModule', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Ext/ObjectModule.bsl'; + const filePath = node.path + '/Ext/ObjectModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openManagerModule', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Ext/ManagerModule.bsl'; + const filePath = node.path + '/Ext/ManagerModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openForm', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Ext/Form/Module.bsl'; + const filePath = node.path + '/Ext/Form/Module.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openModule', (node: TreeItem) => { - const filePath = rootPath + '/CommonModules/' + node.label + '/Ext/Module.bsl'; + const filePath = node.path + '/Ext/Module.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openCommandModule', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Commands/' + node.label + '/Ext/CommandModule.bsl'; + const filePath = node.path + '/Ext/CommandModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openRecordSetModule', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '/Ext/RecordSetModule.bsl'; + const filePath = node.path + '/Ext/RecordSetModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openValueManagerModule', (node: TreeItem) => { - const filePath = rootPath + '/Constants/' + node.label + '/Ext/ValueManagerModule.bsl'; + const filePath = node.path + '/Ext/ValueManagerModule.bsl'; OpenFile(filePath); }); vscode.commands.registerCommand('metadataViewer.openXml', (node: TreeItem) => { - const filePath = rootPath + '/' + node.path + '.xml'; + const filePath = node.path + '.xml'; OpenFile(filePath); }); diff --git a/src/metadataView.ts b/src/metadataView.ts index 22b2c91..d27c638 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -1,4 +1,5 @@ import * as fs from 'fs'; +import * as glob from 'fast-glob'; import * as vscode from 'vscode'; import * as xml2js from 'xml2js'; import { posix } from 'path'; @@ -58,14 +59,19 @@ export class TreeItem extends vscode.TreeItem { id: string; children: TreeItem[] | undefined; path?: string; + parentId = ''; + isConfiguration = false; constructor(id: string, label: string, children?: TreeItem[]) { super( label, children === undefined ? vscode.TreeItemCollapsibleState.None : - vscode.TreeItemCollapsibleState.Collapsed); + id === 'configurations' ? + vscode.TreeItemCollapsibleState.Expanded : + vscode.TreeItemCollapsibleState.Collapsed); this.id = id; + children?.forEach(ch => ch.parentId = id); this.children = children; } } @@ -75,9 +81,14 @@ export class MetadataView { const view = vscode.window.createTreeView('metadataView', { treeDataProvider: NodeWithIdTreeDataProvider(), showCollapseAll: true }); context.subscriptions.push(view); + view.onDidExpandElement(e => { + this.expand(e.element); + }); + vscode.workspace.workspaceFolders?.map(folder => { const folderUri = folder.uri; LoadAndParseConfigurationXml(folderUri); + view.reveal(tree[0]); }); vscode.commands.registerCommand('metadataViewer.openPredefinedData', (item) => this.openPredefinedData(context, item)); @@ -102,73 +113,74 @@ export class MetadataView { } } } + + private expand(element: TreeItem) { + if (!element.isConfiguration) { + return; + } + + const rootPath = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0)) + ? vscode.workspace.workspaceFolders[0].uri : undefined; + + if (rootPath) { + vscode.workspace.fs.readFile(rootPath.with({ path: posix.join(element.id, 'ConfigDumpInfo.xml') })) + .then(configXml => { + xml2js.parseString(configXml, (err, result) => { + const typedResult = result as MetadataFile; + CreateTreeElements(element, typedResult); + }); + }); + } + } } const tree: TreeItem[] = [ - GetTreeItem({ $: { id: 'configuration', name: 'Конфигурация' } }, { path: 'Configuration', context: 'main', children: [ - GetTreeItem({ $: { id: 'common', name: 'Общие' } }, { icon: 'common', children: [ - GetTreeItem({ $: { id: 'subsystems', name: 'Подсистемы' } }, { icon: 'subsystem', children: [] }), - GetTreeItem({ $: { id: 'commonModules', name: 'Общие модули' } }, { icon: 'commonModule', children: [] }), - GetTreeItem({ $: { id: 'sessionParameters', name: 'Параметры сеанса' } }, { icon: 'sessionParameter', children: [] }), - GetTreeItem({ $: { id: 'roles', name: 'Роли' } }, { icon: 'role', children: [] }), - GetTreeItem({ $: { id: 'commonAttributes', name: 'Общие реквизиты' } }, { icon: 'attribute', children: [] }), - GetTreeItem({ $: { id: 'exchangePlans', name: 'Планы обмена' } }, { icon: 'exchangePlan', children: [] }), - GetTreeItem({ $: { id: 'filterCriteria', name: 'Критерии отбора' } }, { icon: 'filterCriteria', children: [] }), - GetTreeItem({ $: { id: 'eventSubscriptions', name: 'Подписки на события' } }, { icon: 'eventSubscription', children: [] }), - GetTreeItem({ $: { id: 'scheduledJobs', name: 'Регламентные задания' } }, { icon: 'scheduledJob', children: [] }), - //GetTreeItem({ $: { id: '', name: 'Боты' } }, { children: [] }), - GetTreeItem({ $: { id: 'functionalOptions', name: 'Функциональные опции' } }, { children: [] }), - GetTreeItem({ $: { id: 'functionalOptionsParameters', name: 'Параметры функциональных опций' } }, { children: [] }), - GetTreeItem({ $: { id: 'definedTypes', name: 'Определяемые типы' } }, { children: [] }), - GetTreeItem({ $: { id: 'settingsStorages', name: 'Хранилища настроек' } }, { children: [] }), - GetTreeItem({ $: { id: 'commonCommands', name: 'Общие команды' } }, { children: [] }), - GetTreeItem({ $: { id: 'commandGroups', name: 'Группы команд' } }, { children: [] }), - GetTreeItem({ $: { id: 'commonForms', name: 'Общие формы' } }, { children: [] }), - GetTreeItem({ $: { id: 'commonTemplates', name: 'Общие макеты' } }, { children: [] }), - GetTreeItem({ $: { id: 'commonPictures', name: 'Общие картинки' } }, { children: [] }), - GetTreeItem({ $: { id: 'xdtoPackages', name: 'XDTO-пакеты' } }, { children: [] }), - GetTreeItem({ $: { id: 'webServices', name: 'Web-сервисы' } }, { children: [] }), - GetTreeItem({ $: { id: 'httpServices', name: 'HTTP-сервисы' } }, { children: [] }), - GetTreeItem({ $: { id: 'wsReferences', name: 'WS-ссылки' } }, { children: [] }), - //GetTreeItem({ $: { id: '', name: 'Сервисы интеграции' } }, { children: [] }), - GetTreeItem({ $: { id: 'styleItems', name: 'Элементы стиля' } }, { children: [] }), - //GetTreeItem({ $: { id: '', name: 'Стили' } }, { children: [] }), - GetTreeItem({ $: { id: 'languages', name: 'Языки' } }, { children: [] }), - ]}), - GetTreeItem({ $: { id: 'constants', name: 'Константы' } }, { icon: 'constant', children: [] }), - GetTreeItem({ $: { id: 'catalogs', name: 'Справочники' } }, { icon: 'catalog', children: [] }), - GetTreeItem({ $: { id: 'documents', name: 'Документы' } }, { icon: 'document', children: [ - GetTreeItem({ $: { id: 'documentNumerators', name: 'Нумераторы' } }, { children: [] }), - GetTreeItem({ $: { id: 'sequences', name: 'Последовательности' } }, { children: [] }), - ]}), - GetTreeItem({ $: { id: 'documentJournals', name: 'Журналы документов' } }, { icon: 'documentJournal', children: [] }), - GetTreeItem({ $: { id: 'enums', name: 'Перечисления' } }, { icon: 'enum', children: [] }), - GetTreeItem({ $: { id: 'reports', name: 'Отчеты' } }, { icon: 'report', children: [] }), - GetTreeItem({ $: { id: 'dataProcessors', name: 'Обработки' } }, { icon: 'dataProcessor', children: [] }), - GetTreeItem({ $: { id: 'chartsOfCharacteristicTypes', name: 'Планы видов характеристик' } }, { icon: 'chartsOfCharacteristicType', children: [] }), - GetTreeItem({ $: { id: 'chartsOfAccounts', name: 'Планы счетов' } }, { icon: 'chartsOfAccount', children: [] }), - GetTreeItem({ $: { id: 'chartsOfCalculationTypes', name: 'Планы видов расчета' } }, { icon: 'chartsOfCalculationType', children: [] }), - GetTreeItem({ $: { id: 'informationRegisters', name: 'Регистры сведений' } }, { icon: 'informationRegister', children: [] }), - GetTreeItem({ $: { id: 'accumulationRegisters', name: 'Регистры накопления' } }, { icon: 'accumulationRegister', children: [] }), - GetTreeItem({ $: { id: 'accountingRegisters', name: 'Регистры бухгалтерии', } }, { icon: 'accountingRegister', children: [] }), - GetTreeItem({ $: { id: 'calculationRegisters', name: 'Регистры расчета', } }, { icon: 'calculationRegister', children: [] }), - GetTreeItem({ $: { id: 'businessProcesses', name: 'Бизнес-процессы', } }, { icon: 'businessProcess', children: [] }), - GetTreeItem({ $: { id: 'tasks', name: 'Задачи', } }, { icon: 'task', children: [] }), - GetTreeItem({ $: { id: 'externalDataSources', name: 'Внешние источники данных', } }, { icon: 'externalDataSource', children: [] }), - ]}), + GetTreeItem('configurations', 'Конфигурации', { children: [] }) ]; function LoadAndParseConfigurationXml(uri: vscode.Uri) { - vscode.workspace.fs.readFile(uri.with({ path: posix.join(uri.path, 'ConfigDumpInfo.xml') })) - .then(configXml => { - xml2js.parseString(configXml, (err, result) => { - const typedResult = result as MetadataFile; - CreateTreeElements(typedResult); - }); - }); + console.time('glob'); + const files = glob.sync([ '**/ConfigDumpInfo.xml', '**/Configuration.xml' ], { + dot: true, + cwd: uri.fsPath, + absolute: true, + }); + console.timeEnd('glob'); + + const configurations = files.reduce<{ [key: string]: string[] }>((previous, current) => { + const key = current.split('/').slice(0, -1).join('/'); + if (!previous[key]) { + previous[key] = []; + } + previous[key].push(current); + return previous; + }, {}); + + const filtered = Object + .keys(configurations) + .filter(f => configurations[f].length === 2); + + filtered.forEach(fc => { + vscode.workspace.fs.readFile(uri.with({ path: posix.join(fc, 'Configuration.xml') })) + .then(configXml => { + xml2js.parseString(configXml, (err, result) => { + let synonym = result.MetaDataObject.Configuration[0].Properties[0].Synonym[0]["v8:item"][0]["v8:content"][0]; + if (!synonym) { + synonym = result.MetaDataObject.Configuration[0].Properties[0].Name[0]; + } + + const treeItem = new TreeItem(fc, `${synonym} (${fc})`, CreateMetadata(fc)); + treeItem.contextValue = 'main'; + treeItem.path = fc; + treeItem.isConfiguration = true; + + tree[0].children?.push(treeItem); + }); + }); + }); } -function CreateTreeElements(metadataFile: MetadataFile) { +function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { const versionMetadata = metadataFile.ConfigDumpInfo.ConfigVersions[0].Metadata; console.time('reduce'); @@ -178,13 +190,25 @@ function CreateTreeElements(metadataFile: MetadataFile) { if (!previous.form[objectName]) { previous.form[objectName] = []; } - previous.form[objectName].push(GetTreeItem(current, { - icon: 'form', path: `${CreatePath(objectName)}/Forms/${current.$.name.split('.').pop()}`, context: 'form' })); + previous.form[objectName].push(GetTreeItem( + element.id + '/' + current.$.id, + current.$.name, + { + icon: 'form', + context: 'form', + path: `${element.id}/${CreatePath(objectName)}/Forms/${current.$.name.split('.').pop()}`, + })); } else if (current.$.name.includes('.Template.') && !current.$.name.endsWith('.Template')) { if (!previous.template[objectName]) { previous.template[objectName] = []; } - previous.template[objectName].push(GetTreeItem(current, { icon: 'template' })); + previous.template[objectName].push(GetTreeItem( + element.id + '/' + current.$.id, + current.$.name, + { + icon: 'template', + path: `${element.id}/${CreatePath(objectName)}/Templates/${current.$.name.split('.').pop()}`, + })); } return previous; }, { form: {}, template: {} }); @@ -193,67 +217,181 @@ function CreateTreeElements(metadataFile: MetadataFile) { if (current.$.name.split('.').length !== 2) { return previous; } + const treeItemId = element.id + '/' + current.$.id; + const treeItemPath = `${element.id}/${CreatePath(current.$.name)}`; if (current.$.name.startsWith('CommonModule.')) { - previous.commonModule.push(GetTreeItem(current, { icon: 'commonModule', context: 'module' })); + previous.commonModule.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'commonModule', + context: 'module', + path: treeItemPath, + })); } else if (current.$.name.startsWith('SessionParameter.')) { - previous.sessionParameter.push(GetTreeItem(current, { icon: 'sessionParameter' })); + previous.sessionParameter.push(GetTreeItem(treeItemId, current.$.name, { icon: 'sessionParameter' })); } else if (current.$.name.startsWith('Role.')) { - previous.role.push(GetTreeItem(current, { icon: 'role' })); + previous.role.push(GetTreeItem(treeItemId, current.$.name, { icon: 'role' })); } else if (current.$.name.startsWith('CommonAttribute.')) { - previous.commonAttribute.push(GetTreeItem(current, { icon: 'attribute' })); + previous.commonAttribute.push(GetTreeItem(treeItemId, current.$.name, { icon: 'attribute' })); } else if (current.$.name.startsWith('ExchangePlan.')) { - previous.exchangePlan.push(GetTreeItem(current, - { icon: 'exchangePlan', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.exchangePlan.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'exchangePlan', + context: 'object_and_manager', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } if (current.$.name.startsWith('Constant.')) { - previous.constant.push(GetTreeItem(current, { icon: 'constant', context: 'valueManager_and_manager' })); + previous.constant.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'constant', + context: 'valueManager_and_manager', + path: treeItemPath, + })); } if (current.$.name.startsWith('Catalog.')) { - previous.catalog.push(GetTreeItem(current, { - icon: 'catalog', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.catalog.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'catalog', + context: 'object_and_manager_and_predefined', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('Document.')) { - previous.document.push(GetTreeItem(current, { - icon: 'document', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.document.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'document', + context: 'object_and_manager', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('DocumentJournal.')) { - previous.documentJournal.push(GetTreeItem(current, { - icon: 'documentJournal', context: 'manager', children: FillDocumentJournalItemsByMetadata(current, attributeReduceResult) })); + previous.documentJournal.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'documentJournal', + context: 'manager', + path: treeItemPath, + children: FillDocumentJournalItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } if (current.$.name.startsWith('Enum.')) { - previous.enum.push(GetTreeItem(current, { - icon: 'enum', context: 'manager', children: FillEnumItemsByMetadata(current, attributeReduceResult) })); + previous.enum.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'enum', + context: 'manager', + path: treeItemPath, + children: FillEnumItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('Report.')) { - previous.report.push(GetTreeItem(current, { - icon: 'report', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.report.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'report', + context: 'object_and_manager', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('DataProcessor.')) { - previous.dataProcessor.push(GetTreeItem(current, { - icon: 'dataProcessor', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.dataProcessor.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'dataProcessor', + context: 'object_and_manager', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('ChartOfCharacteristicTypes.')) { - previous.сhartOfCharacteristicTypes.push(GetTreeItem(current, { - icon: 'chartsOfCharacteristicType', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.сhartOfCharacteristicTypes.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'chartsOfCharacteristicType', + context: 'object_and_manager_and_predefined', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('ChartOfAccounts.')) { - previous.chartOfAccounts.push(GetTreeItem(current, { - icon: 'chartsOfAccount', context: 'object_and_manager_and_predefined', children: FillChartOfAccountsItemsByMetadata(current, attributeReduceResult) })); + previous.chartOfAccounts.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'chartsOfAccount', + context: 'object_and_manager_and_predefined', + path: treeItemPath, + children: FillChartOfAccountsItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('ChartOfCalculationTypes.')) { - previous.chartOfCalculationTypes.push(GetTreeItem(current, { - icon: 'chartsOfCalculationType', context: 'object_and_manager_and_predefined', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.chartOfCalculationTypes.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'chartsOfCalculationType', + context: 'object_and_manager_and_predefined', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('InformationRegister.')) { - previous.informationRegister.push(GetTreeItem(current, { - icon: 'informationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + previous.informationRegister.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'informationRegister', + context: 'recordset_and_manager', + path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('AccumulationRegister.')) { - previous.accumulationRegister.push(GetTreeItem(current, { - icon: 'accumulationRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + previous.accumulationRegister.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'accumulationRegister', + context: 'recordset_and_manager', + path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('AccountingRegister.')) { - previous.accountingRegister.push(GetTreeItem(current, { - icon: 'accountingRegister', context: 'recordset_and_manager', children: FillRegisterItemsByMetadata(current, attributeReduceResult) })); + previous.accountingRegister.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'accountingRegister', + context: 'recordset_and_manager', + path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('CalculationRegister.')) { - previous.calculationRegister.push(GetTreeItem(current, { - icon: 'calculationRegister', context: 'recordset_and_manager', children: FillCalculationRegisterItemsByMetadata(current, attributeReduceResult) })); + previous.calculationRegister.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'calculationRegister', + context: 'recordset_and_manager', + path: treeItemPath, + children: FillCalculationRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('BusinessProcess.')) { - previous.businessProcess.push(GetTreeItem(current, { - icon: 'businessProcess', context: 'object_and_manager', children: FillObjectItemsByMetadata(current, attributeReduceResult) })); + previous.businessProcess.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'businessProcess', + context: 'object_and_manager', + path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('Task.')) { - previous.task.push(GetTreeItem(current, { - icon: 'task', context: 'object_and_manager', children: FillTaskItemsByMetadata(current, attributeReduceResult) })); + previous.task.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'task', + context: 'object_and_manager', + path: treeItemPath, + children: FillTaskItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } else if (current.$.name.startsWith('ExternalDataSource.')) { - previous.externalDataSource.push(GetTreeItem(current, { - icon: 'externalDataSource', children: FillExternalDataSourceItemsByMetadata(current, attributeReduceResult) })); + previous.externalDataSource.push(GetTreeItem( + treeItemId, current.$.name, + { + icon: 'externalDataSource', + children: FillExternalDataSourceItemsByMetadata(element.id + '/', current, attributeReduceResult) + })); } return previous; @@ -282,152 +420,152 @@ function CreateTreeElements(metadataFile: MetadataFile) { externalDataSource: [], }); - SearchTree(tree[0], 'commonModules')!.children = reduceResult.commonModule; - SearchTree(tree[0], 'sessionParameters')!.children = reduceResult.sessionParameter; - SearchTree(tree[0], 'roles')!.children = reduceResult.role; - SearchTree(tree[0], 'commonAttributes')!.children = reduceResult.commonAttribute; - SearchTree(tree[0], 'exchangePlans')!.children = reduceResult.exchangePlan; - SearchTree(tree[0], 'constants')!.children = reduceResult.constant; - SearchTree(tree[0], 'catalogs')!.children = reduceResult.catalog; + SearchTree(element, element.id + '/commonModules')!.children = reduceResult.commonModule; + SearchTree(element, element.id + '/sessionParameters')!.children = reduceResult.sessionParameter; + SearchTree(element, element.id + '/roles')!.children = reduceResult.role; + SearchTree(element, element.id + '/commonAttributes')!.children = reduceResult.commonAttribute; + SearchTree(element, element.id + '/exchangePlans')!.children = reduceResult.exchangePlan; + SearchTree(element, element.id + '/constants')!.children = reduceResult.constant; + SearchTree(element, element.id + '/catalogs')!.children = reduceResult.catalog; - const documents = SearchTree(tree[0], 'documents'); + const documents = SearchTree(element, element.id + '/documents'); documents!.children = [ ...documents!.children ?? [], ...reduceResult.document]; - SearchTree(tree[0], 'documentJournals')!.children = reduceResult.documentJournal; - SearchTree(tree[0], 'enums')!.children = reduceResult.enum; - SearchTree(tree[0], 'reports')!.children = reduceResult.report; - SearchTree(tree[0], 'dataProcessors')!.children = reduceResult.dataProcessor; - SearchTree(tree[0], 'chartsOfCharacteristicTypes')!.children = reduceResult.сhartOfCharacteristicTypes; - SearchTree(tree[0], 'chartsOfAccounts')!.children = reduceResult.chartOfAccounts; - SearchTree(tree[0], 'chartsOfCalculationTypes')!.children = reduceResult.chartOfCalculationTypes; - SearchTree(tree[0], 'informationRegisters')!.children = reduceResult.informationRegister; - SearchTree(tree[0], 'accumulationRegisters')!.children = reduceResult.accumulationRegister; - SearchTree(tree[0], 'accountingRegisters')!.children = reduceResult.accountingRegister; - SearchTree(tree[0], 'calculationRegisters')!.children = reduceResult.calculationRegister; - SearchTree(tree[0], 'businessProcesses')!.children = reduceResult.businessProcess; - SearchTree(tree[0], 'tasks')!.children = reduceResult.task; - SearchTree(tree[0], 'externalDataSources')!.children = reduceResult.externalDataSource; + SearchTree(element, element.id + '/documentJournals')!.children = reduceResult.documentJournal; + SearchTree(element, element.id + '/enums')!.children = reduceResult.enum; + SearchTree(element, element.id + '/reports')!.children = reduceResult.report; + SearchTree(element, element.id + '/dataProcessors')!.children = reduceResult.dataProcessor; + SearchTree(element, element.id + '/chartsOfCharacteristicTypes')!.children = reduceResult.сhartOfCharacteristicTypes; + SearchTree(element, element.id + '/chartsOfAccounts')!.children = reduceResult.chartOfAccounts; + SearchTree(element, element.id + '/chartsOfCalculationTypes')!.children = reduceResult.chartOfCalculationTypes; + SearchTree(element, element.id + '/informationRegisters')!.children = reduceResult.informationRegister; + SearchTree(element, element.id + '/accumulationRegisters')!.children = reduceResult.accumulationRegister; + SearchTree(element, element.id + '/accountingRegisters')!.children = reduceResult.accountingRegister; + SearchTree(element, element.id + '/calculationRegisters')!.children = reduceResult.calculationRegister; + SearchTree(element, element.id + '/businessProcesses')!.children = reduceResult.businessProcess; + SearchTree(element, element.id + '/tasks')!.children = reduceResult.task; + SearchTree(element, element.id + '/externalDataSources')!.children = reduceResult.externalDataSource; console.timeEnd('reduce'); } -function FillObjectItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillObjectItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const attributes = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.Attribute.')) - .map(m => GetTreeItem(m, { icon: 'attribute' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'attribute' })); const tabularSection = (versionMetadata.Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.TabularSection.') && !m.$.name.includes('.Attribute.')) - .map(m => GetTreeItem(m, { + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'tabularSection', // TODO: undefined for children if length eq zero children: (versionMetadata.Metadata ?? []) .filter(f => f.$.name.startsWith(versionMetadata.$.name + '.TabularSection.' + m.$.name.split('.').pop()) && f.$.name.includes('.Attribute.')) - .map(f => GetTreeItem(f, { icon: 'attribute' })) })); + .map(f => GetTreeItem(idPrefix + f.$.id, f.$.name, { icon: 'attribute' })) })); const items = [ - GetTreeItem({ $: { id: '', name: 'Реквизиты'}}, { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), - GetTreeItem({ $: { id: '', name: 'Табличные части'}}, { icon: 'tabularSection', children: tabularSection }), + GetTreeItem('', 'Реквизиты', { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), + GetTreeItem('', 'Табличные части', { icon: 'tabularSection', children: tabularSection }), ]; - return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; + return [ ...items, ...FillCommonItems(idPrefix , versionMetadata, objectData) ]; } -function FillDocumentJournalItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillDocumentJournalItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const columns = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.Column.')) - .map(m => GetTreeItem(m, { icon: 'column' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'column' })); const items = [ - GetTreeItem({ $: { id: '', name: 'Графы'}}, { icon: 'column', children: columns.length === 0 ? undefined : columns }), + GetTreeItem('', 'Графы', { icon: 'column', children: columns.length === 0 ? undefined : columns }), ]; - return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; + return [ ...items, ...FillCommonItems(idPrefix, versionMetadata, objectData) ]; } -function FillEnumItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillEnumItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const values = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith('Enum.')) - .map(m => GetTreeItem(m, { icon: 'attribute' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'attribute' })); const items = [ - GetTreeItem({ $: { id: '', name: 'Значения'}}, { icon: 'attribute', children: values.length === 0 ? undefined : values }), + GetTreeItem('', 'Значения', { icon: 'attribute', children: values.length === 0 ? undefined : values }), ]; - return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; + return [ ...items, ...FillCommonItems(idPrefix, versionMetadata, objectData) ]; } -function FillChartOfAccountsItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillChartOfAccountsItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const accountingFlags = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.AccountingFlag.')) - .map(m => GetTreeItem(m, { icon: 'accountingFlag' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'accountingFlag' })); const extDimensionAccountingFlag = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.ExtDimensionAccountingFlag.')) - .map(m => GetTreeItem(m, { icon: 'extDimensionAccountingFlag' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'extDimensionAccountingFlag' })); const items = [ - GetTreeItem({ $: { id: '', name: 'Признаки учета'}}, { icon: 'accountingFlag', children: accountingFlags.length === 0 ? undefined : accountingFlags }), - GetTreeItem({ $: { id: '', name: 'Признаки учета субконто'}}, { + GetTreeItem('', 'Признаки учета', { icon: 'accountingFlag', children: accountingFlags.length === 0 ? undefined : accountingFlags }), + GetTreeItem('', 'Признаки учета субконто', { icon: 'extDimensionAccountingFlag', children: extDimensionAccountingFlag.length === 0 ? undefined : extDimensionAccountingFlag }), ]; - return [ ...items, ...FillObjectItemsByMetadata(versionMetadata, objectData) ] + return [ ...items, ...FillObjectItemsByMetadata(idPrefix, versionMetadata, objectData) ] .sort((x, y) => { return x.label == "Реквизиты" ? -1 : y.label == "Реквизиты" ? 1 : 0; }); } -function FillRegisterItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillRegisterItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const dimensions = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.Dimension.')) - .map(m => GetTreeItem(m, { icon: 'dimension' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'dimension' })); const resources = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.Resource.')) - .map(m => GetTreeItem(m, { icon: 'resource' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'resource' })); const attributes = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.Attribute.')) - .map(m => GetTreeItem(m, { icon: 'attribute' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'attribute' })); const items = [ - GetTreeItem({ $: { id: '', name: 'Измерения'}}, { icon: 'dimension', children: dimensions.length === 0 ? undefined : dimensions }), - GetTreeItem({ $: { id: '', name: 'Ресурсы'}}, { icon: 'resource', children: resources.length === 0 ? undefined : resources }), - GetTreeItem({ $: { id: '', name: 'Реквизиты'}}, { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), + GetTreeItem('', 'Измерения', { icon: 'dimension', children: dimensions.length === 0 ? undefined : dimensions }), + GetTreeItem('', 'Ресурсы', { icon: 'resource', children: resources.length === 0 ? undefined : resources }), + GetTreeItem('', 'Реквизиты', { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), ]; - return [ ...items, ...FillCommonItems(versionMetadata, objectData) ]; + return [ ...items, ...FillCommonItems(idPrefix, versionMetadata, objectData) ]; } -function FillCalculationRegisterItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillCalculationRegisterItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const items: TreeItem[] = [ // TODO: Перерасчеты ]; - return [ ...items, ...FillRegisterItemsByMetadata(versionMetadata, objectData) ]; + return [ ...items, ...FillRegisterItemsByMetadata(idPrefix, versionMetadata, objectData) ]; } -function FillTaskItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillTaskItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const attributes = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.startsWith(versionMetadata.$.name + '.AddressingAttribute.')) - .map(m => GetTreeItem(m, { icon: 'attribute' })); + .map(m => GetTreeItem(idPrefix + m.$.id, m.$.name, { icon: 'attribute' })); const items = [ - GetTreeItem({ $: { id: '', name: 'Реквизиты адресации'}}, { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), + GetTreeItem('', 'Реквизиты адресации', { icon: 'attribute', children: attributes.length === 0 ? undefined : attributes }), ]; - return [ ...items, ...FillObjectItemsByMetadata(versionMetadata, objectData) ] + return [ ...items, ...FillObjectItemsByMetadata(idPrefix, versionMetadata, objectData) ] .sort((x, y) => { return x.label == "Реквизиты" ? -1 : y.label == "Реквизиты" ? 1 : 0; }); } -function FillExternalDataSourceItemsByMetadata(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillExternalDataSourceItemsByMetadata(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const items: TreeItem[] = [ // TODO: ]; @@ -435,30 +573,37 @@ function FillExternalDataSourceItemsByMetadata(versionMetadata: VersionMetadata, return items; } -function FillCommonItems(versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { +function FillCommonItems(idPrefix: string, versionMetadata: VersionMetadata, objectData: MetadataDictionaries): TreeItem[] { const commands = (versionMetadata .Metadata ?? []) .filter(m => m.$.name.includes('.Command.')) - .map(m => GetTreeItem(m, { icon: 'command', context: 'command' })); + .map(m => GetTreeItem( + idPrefix + m.$.id, + m.$.name, + { + icon: 'command', + context: 'command', + path: `${idPrefix}${CreatePath(m.$.name)}/Commands/${m.$.name.split('.').pop()}`, + })); return [ - GetTreeItem({ $: { id: '', name: 'Формы'}}, { icon: 'form', children: objectData.form[versionMetadata.$.name] }), - GetTreeItem({ $: { id: '', name: 'Команды'}}, { icon: 'command', children: commands.length === 0 ? undefined : commands }), - GetTreeItem({ $: { id: '', name: 'Макеты'}}, { icon: 'template', children: objectData.template[versionMetadata.$.name] }), + GetTreeItem('', 'Формы', { icon: 'form', children: objectData.form[versionMetadata.$.name] }), + GetTreeItem('', 'Команды', { icon: 'command', children: commands.length === 0 ? undefined : commands }), + GetTreeItem('', 'Макеты', { icon: 'template', children: objectData.template[versionMetadata.$.name] }), ]; } -function GetTreeItem(element: ObjectMetadata, params?: TreeItemParams ): TreeItem { - const treeItem = new TreeItem(element.$.id, element.$.name.split('.').pop() ?? '', params?.children); +function GetTreeItem(id: string, name: string, params: TreeItemParams ): TreeItem { + const treeItem = new TreeItem(id, name.split('.').pop() ?? '', params?.children); - if (params?.icon) { + if (params.icon) { treeItem.iconPath = getIconPath(params.icon); } - if (params?.context) { + if (params.context) { treeItem.contextValue = params.context; } - treeItem.path = params?.path ?? CreatePath(element.$.name.split('.').slice(0,2).join('.')); - if (params?.command && params.commandTitle) { + treeItem.path = params.path; // ?? CreatePath(name.split('.').slice(0,2).join('.')); + if (params.command && params.commandTitle) { treeItem.command = { command: params.command, title: params.commandTitle }; } @@ -500,7 +645,7 @@ function CreatePath(name: string): string { .replace('BusinessProcess.', 'BusinessProcesses/') .replace('Task.', 'Tasks/') .replace('ExternalDataSource.', 'ExternalDataSources/'); - } +} function NodeWithIdTreeDataProvider(): vscode.TreeDataProvider { return { @@ -513,10 +658,67 @@ function NodeWithIdTreeDataProvider(): vscode.TreeDataProvider { getTreeItem: (element: TreeItem): vscode.TreeItem | Thenable => { return element; }, + getParent(element: TreeItem): TreeItem | undefined{ + return SearchTree(tree[0], element.parentId) ?? undefined; + }, }; } function getIconPath(icon: string): string { const isDark = vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark; return path.join(__filename, '..', '..', 'resources', isDark ? 'dark' : 'light', icon + '.svg'); +} + +function CreateMetadata(idPrefix: string) { + return [ + GetTreeItem(idPrefix + '/common', 'Общие', { icon: 'common', children: [ + GetTreeItem(idPrefix + '/subsystems', 'Подсистемы', { icon: 'subsystem', children: [] }), + GetTreeItem(idPrefix + '/commonModules', 'Общие модули', { icon: 'commonModule', children: [] }), + GetTreeItem(idPrefix + '/sessionParameters', 'Параметры сеанса', { icon: 'sessionParameter', children: [] }), + GetTreeItem(idPrefix + '/roles', 'Роли', { icon: 'role', children: [] }), + GetTreeItem(idPrefix + '/commonAttributes', 'Общие реквизиты', { icon: 'attribute', children: [] }), + GetTreeItem(idPrefix + '/exchangePlans', 'Планы обмена', { icon: 'exchangePlan', children: [] }), + GetTreeItem(idPrefix + '/filterCriteria', 'Критерии отбора', { icon: 'filterCriteria', children: [] }), + GetTreeItem(idPrefix + '/eventSubscriptions', 'Подписки на события', { icon: 'eventSubscription', children: [] }), + GetTreeItem(idPrefix + '/scheduledJobs', 'Регламентные задания', { icon: 'scheduledJob', children: [] }), + //GetTreeItem(idPrefix + '', 'Боты', { children: [] }), + GetTreeItem(idPrefix + '/functionalOptions', 'Функциональные опции', { children: [] }), + GetTreeItem(idPrefix + '/functionalOptionsParameters', 'Параметры функциональных опций', { children: [] }), + GetTreeItem(idPrefix + '/definedTypes', 'Определяемые типы', { children: [] }), + GetTreeItem(idPrefix + '/settingsStorages', 'Хранилища настроек', { children: [] }), + GetTreeItem(idPrefix + '/commonCommands', 'Общие команды', { children: [] }), + GetTreeItem(idPrefix + '/commandGroups', 'Группы команд', { children: [] }), + GetTreeItem(idPrefix + '/commonForms', 'Общие формы', { children: [] }), + GetTreeItem(idPrefix + '/commonTemplates', 'Общие макеты', { children: [] }), + GetTreeItem(idPrefix + '/commonPictures', 'Общие картинки', { children: [] }), + GetTreeItem(idPrefix + '/xdtoPackages', 'XDTO-пакеты', { children: [] }), + GetTreeItem(idPrefix + '/webServices', 'Web-сервисы', { children: [] }), + GetTreeItem(idPrefix + '/httpServices', 'HTTP-сервисы', { children: [] }), + GetTreeItem(idPrefix + '/wsReferences', 'WS-ссылки', { children: [] }), + //GetTreeItem(idPrefix + '/', 'Сервисы интеграции', { children: [] }), + GetTreeItem(idPrefix + '/styleItems', 'Элементы стиля', { children: [] }), + //GetTreeItem(idPrefix + '/', 'Стили', { children: [] }), + GetTreeItem(idPrefix + '/languages', 'Языки', { children: [] }), + ]}), + GetTreeItem(idPrefix + '/constants', 'Константы', { icon: 'constant', children: [] }), + GetTreeItem(idPrefix + '/catalogs', 'Справочники', { icon: 'catalog', children: [] }), + GetTreeItem(idPrefix + '/documents', 'Документы', { icon: 'document', children: [ + GetTreeItem(idPrefix + '/documentNumerators', 'Нумераторы', { children: [] }), + GetTreeItem(idPrefix + '/sequences', 'Последовательности', { children: [] }), + ]}), + GetTreeItem(idPrefix + '/documentJournals', 'Журналы документов', { icon: 'documentJournal', children: [] }), + GetTreeItem(idPrefix + '/enums', 'Перечисления', { icon: 'enum', children: [] }), + GetTreeItem(idPrefix + '/reports', 'Отчеты', { icon: 'report', children: [] }), + GetTreeItem(idPrefix + '/dataProcessors', 'Обработки', { icon: 'dataProcessor', children: [] }), + GetTreeItem(idPrefix + '/chartsOfCharacteristicTypes', 'Планы видов характеристик', { icon: 'chartsOfCharacteristicType', children: [] }), + GetTreeItem(idPrefix + '/chartsOfAccounts', 'Планы счетов', { icon: 'chartsOfAccount', children: [] }), + GetTreeItem(idPrefix + '/chartsOfCalculationTypes', 'Планы видов расчета', { icon: 'chartsOfCalculationType', children: [] }), + GetTreeItem(idPrefix + '/informationRegisters', 'Регистры сведений', { icon: 'informationRegister', children: [] }), + GetTreeItem(idPrefix + '/accumulationRegisters', 'Регистры накопления', { icon: 'accumulationRegister', children: [] }), + GetTreeItem(idPrefix + '/accountingRegisters', 'Регистры бухгалтерии', { icon: 'accountingRegister', children: [] }), + GetTreeItem(idPrefix + '/calculationRegisters', 'Регистры расчета', { icon: 'calculationRegister', children: [] }), + GetTreeItem(idPrefix + '/businessProcesses', 'Бизнес-процессы', { icon: 'businessProcess', children: [] }), + GetTreeItem(idPrefix + '/tasks', 'Задачи', { icon: 'task', children: [] }), + GetTreeItem(idPrefix + '/externalDataSources', 'Внешние источники данных', { icon: 'externalDataSource', children: [] }), + ]; } \ No newline at end of file From fb65e54f522ccadceb109b2d74920f70d632a265 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 00:51:31 +0300 Subject: [PATCH 09/16] =?UTF-8?q?=D0=9D=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=B0=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D0=B5=D0=B9?= =?UTF-8?q?=20=D0=B2=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20glob?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 13 ++++++++++++- package.nls.json | 3 ++- package.nls.ru.json | 3 ++- src/metadataView.ts | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5a2ad22..339880f 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,18 @@ } ] }, - "configuration": [] + "configuration": [ + { + "title": "1C Metadata Viewer", + "properties": { + "conf.metadataViewer.configurationSearchDepth": { + "type": "integer", + "default": 3, + "description": "%1c-metadata-viewer.conf.configurationSearchDepth.title%" + } + } + } + ] }, "scripts": { "vscode:prepublish": "npm run compile", diff --git a/package.nls.json b/package.nls.json index f9a469a..5cbafa6 100644 --- a/package.nls.json +++ b/package.nls.json @@ -10,5 +10,6 @@ "1c-metadata-viewer.openRecordSetModule.title": "Open record set module", "1c-metadata-viewer.openValueManagerModule.title": "Open value manager module", "1c-metadata-viewer.openXml.title": "Open XML", - "1c-metadata-viewer.openPredefinedData.title": "Open predefined data" + "1c-metadata-viewer.openPredefinedData.title": "Open predefined data", + "1c-metadata-viewer.conf.configurationSearchDepth.title": "The number of nesting levels of directories in which 1C:Enterprise configurations are searched" } \ No newline at end of file diff --git a/package.nls.ru.json b/package.nls.ru.json index 5eb9da3..cc6cd40 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -10,5 +10,6 @@ "1c-metadata-viewer.openRecordSetModule.title": "Открыть модуль набора записей", "1c-metadata-viewer.openValueManagerModule.title": "Открыть модуль менеджера значения", "1c-metadata-viewer.openXml.title": "Открыть XML", - "1c-metadata-viewer.openPredefinedData.title": "Открыть предопределенные данные" + "1c-metadata-viewer.openPredefinedData.title": "Открыть предопределенные данные", + "1c-metadata-viewer.conf.configurationSearchDepth.title": "Количество уровней вложенности каталогов в которых осуществляется поиск конфигураций 1С:Предприятия" } \ No newline at end of file diff --git a/src/metadataView.ts b/src/metadataView.ts index d27c638..2c19a48 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -144,6 +144,7 @@ function LoadAndParseConfigurationXml(uri: vscode.Uri) { dot: true, cwd: uri.fsPath, absolute: true, + deep: vscode.workspace.getConfiguration().get('conf.metadataViewer.configurationSearchDepth'), }); console.timeEnd('glob'); From dbb5182b8dcf3d9c76610ac11bb103b99a997af9 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 01:29:43 +0300 Subject: [PATCH 10/16] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/metadataView.ts | 316 ++++++++++++++++++++------------------------ 1 file changed, 142 insertions(+), 174 deletions(-) diff --git a/src/metadataView.ts b/src/metadataView.ts index 2c19a48..59d4fd4 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -220,180 +220,148 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { } const treeItemId = element.id + '/' + current.$.id; const treeItemPath = `${element.id}/${CreatePath(current.$.name)}`; - if (current.$.name.startsWith('CommonModule.')) { - previous.commonModule.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'commonModule', - context: 'module', - path: treeItemPath, - })); - } else if (current.$.name.startsWith('SessionParameter.')) { - previous.sessionParameter.push(GetTreeItem(treeItemId, current.$.name, { icon: 'sessionParameter' })); - } else if (current.$.name.startsWith('Role.')) { - previous.role.push(GetTreeItem(treeItemId, current.$.name, { icon: 'role' })); - } else if (current.$.name.startsWith('CommonAttribute.')) { - previous.commonAttribute.push(GetTreeItem(treeItemId, current.$.name, { icon: 'attribute' })); - } else if (current.$.name.startsWith('ExchangePlan.')) { - previous.exchangePlan.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'exchangePlan', - context: 'object_and_manager', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } if (current.$.name.startsWith('Constant.')) { - previous.constant.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'constant', - context: 'valueManager_and_manager', - path: treeItemPath, - })); - } if (current.$.name.startsWith('Catalog.')) { - previous.catalog.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'catalog', - context: 'object_and_manager_and_predefined', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('Document.')) { - previous.document.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'document', - context: 'object_and_manager', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('DocumentJournal.')) { - previous.documentJournal.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'documentJournal', - context: 'manager', - path: treeItemPath, - children: FillDocumentJournalItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } if (current.$.name.startsWith('Enum.')) { - previous.enum.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'enum', - context: 'manager', - path: treeItemPath, - children: FillEnumItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('Report.')) { - previous.report.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'report', - context: 'object_and_manager', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('DataProcessor.')) { - previous.dataProcessor.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'dataProcessor', - context: 'object_and_manager', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('ChartOfCharacteristicTypes.')) { - previous.сhartOfCharacteristicTypes.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'chartsOfCharacteristicType', - context: 'object_and_manager_and_predefined', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('ChartOfAccounts.')) { - previous.chartOfAccounts.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'chartsOfAccount', - context: 'object_and_manager_and_predefined', - path: treeItemPath, - children: FillChartOfAccountsItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('ChartOfCalculationTypes.')) { - previous.chartOfCalculationTypes.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'chartsOfCalculationType', - context: 'object_and_manager_and_predefined', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('InformationRegister.')) { - previous.informationRegister.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'informationRegister', - context: 'recordset_and_manager', - path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('AccumulationRegister.')) { - previous.accumulationRegister.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'accumulationRegister', - context: 'recordset_and_manager', - path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('AccountingRegister.')) { - previous.accountingRegister.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'accountingRegister', - context: 'recordset_and_manager', - path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('CalculationRegister.')) { - previous.calculationRegister.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'calculationRegister', - context: 'recordset_and_manager', - path: treeItemPath, - children: FillCalculationRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('BusinessProcess.')) { - previous.businessProcess.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'businessProcess', - context: 'object_and_manager', - path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('Task.')) { - previous.task.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'task', - context: 'object_and_manager', - path: treeItemPath, - children: FillTaskItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } else if (current.$.name.startsWith('ExternalDataSource.')) { - previous.externalDataSource.push(GetTreeItem( - treeItemId, current.$.name, - { - icon: 'externalDataSource', - children: FillExternalDataSourceItemsByMetadata(element.id + '/', current, attributeReduceResult) - })); - } + switch (true) { + case current.$.name.startsWith('CommonModule.'): + previous.commonModule.push(GetTreeItem( + treeItemId, current.$.name, + { icon: 'commonModule', context: 'module', path: treeItemPath, })); + + break; + case current.$.name.startsWith('SessionParameter.'): + previous.sessionParameter.push(GetTreeItem(treeItemId, current.$.name, { icon: 'sessionParameter' })); + break; + case current.$.name.startsWith('Role.'): + previous.role.push(GetTreeItem(treeItemId, current.$.name, { icon: 'role' })); + break; + case current.$.name.startsWith('CommonAttribute.'): + previous.commonAttribute.push(GetTreeItem(treeItemId, current.$.name, { icon: 'attribute' })); + break; + case current.$.name.startsWith('ExchangePlan.'): + previous.exchangePlan.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'exchangePlan', context: 'object_and_manager', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('Constant.'): + previous.constant.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'constant', context: 'valueManager_and_manager', path: treeItemPath, })); + + break; + case current.$.name.startsWith('Catalog.'): + previous.catalog.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'catalog', context: 'object_and_manager_and_predefined', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('Document.'): + previous.document.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'document', context: 'object_and_manager', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('DocumentJournal.'): + previous.documentJournal.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'documentJournal', context: 'manager', path: treeItemPath, + children: FillDocumentJournalItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('Enum.'): + previous.enum.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'enum', context: 'manager', path: treeItemPath, + children: FillEnumItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('Report.'): + previous.report.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'report', context: 'object_and_manager', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('DataProcessor.'): + previous.dataProcessor.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'dataProcessor', context: 'object_and_manager', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('ChartOfCharacteristicTypes.'): + previous.сhartOfCharacteristicTypes.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'chartsOfCharacteristicType', context: 'object_and_manager_and_predefined', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('ChartOfAccounts.'): + previous.chartOfAccounts.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'chartsOfAccount', context: 'object_and_manager_and_predefined', path: treeItemPath, + children: FillChartOfAccountsItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('ChartOfCalculationTypes.'): + previous.chartOfCalculationTypes.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'chartsOfCalculationType', context: 'object_and_manager_and_predefined', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('InformationRegister.'): + previous.informationRegister.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'informationRegister', context: 'recordset_and_manager', path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('AccumulationRegister.'): + previous.accumulationRegister.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'accumulationRegister', context: 'recordset_and_manager', path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('AccountingRegister.'): + previous.accountingRegister.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'accountingRegister', context: 'recordset_and_manager', path: treeItemPath, + children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('CalculationRegister.'): + previous.calculationRegister.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'calculationRegister', context: 'recordset_and_manager', path: treeItemPath, + children: FillCalculationRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('BusinessProcess.'): + previous.businessProcess.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'businessProcess', context: 'object_and_manager', path: treeItemPath, + children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('Task.'): + previous.task.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'task', context: 'object_and_manager', path: treeItemPath, + children: FillTaskItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + case current.$.name.startsWith('ExternalDataSource.'): + previous.externalDataSource.push(GetTreeItem( + treeItemId, current.$.name, { + icon: 'externalDataSource', + children: FillExternalDataSourceItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + + break; + } return previous; }, { From fe3ec8b4c655b751a26c3547c577d8efde847a99 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 01:36:22 +0300 Subject: [PATCH 11/16] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=5F2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/metadataView.ts | 46 ++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/metadataView.ts b/src/metadataView.ts index 59d4fd4..d00bdfa 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -184,6 +184,8 @@ function LoadAndParseConfigurationXml(uri: vscode.Uri) { function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { const versionMetadata = metadataFile.ConfigDumpInfo.ConfigVersions[0].Metadata; + const treeItemIdSlash = element.id + '/'; + console.time('reduce'); const attributeReduceResult = versionMetadata.reduce((previous, current) => { const objectName = current.$.name.split('.').slice(0,2).join('.'); @@ -192,7 +194,7 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { previous.form[objectName] = []; } previous.form[objectName].push(GetTreeItem( - element.id + '/' + current.$.id, + treeItemIdSlash + current.$.id, current.$.name, { icon: 'form', @@ -204,7 +206,7 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { previous.template[objectName] = []; } previous.template[objectName].push(GetTreeItem( - element.id + '/' + current.$.id, + treeItemIdSlash + current.$.id, current.$.name, { icon: 'template', @@ -218,8 +220,10 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { if (current.$.name.split('.').length !== 2) { return previous; } - const treeItemId = element.id + '/' + current.$.id; - const treeItemPath = `${element.id}/${CreatePath(current.$.name)}`; + + const treeItemId = treeItemIdSlash + current.$.id; + const treeItemPath = `${treeItemIdSlash}${CreatePath(current.$.name)}`; + switch (true) { case current.$.name.startsWith('CommonModule.'): previous.commonModule.push(GetTreeItem( @@ -240,7 +244,7 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { previous.exchangePlan.push(GetTreeItem( treeItemId, current.$.name, { icon: 'exchangePlan', context: 'object_and_manager', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('Constant.'): @@ -253,112 +257,112 @@ function CreateTreeElements(element: TreeItem, metadataFile: MetadataFile) { previous.catalog.push(GetTreeItem( treeItemId, current.$.name, { icon: 'catalog', context: 'object_and_manager_and_predefined', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('Document.'): previous.document.push(GetTreeItem( treeItemId, current.$.name, { icon: 'document', context: 'object_and_manager', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('DocumentJournal.'): previous.documentJournal.push(GetTreeItem( treeItemId, current.$.name, { icon: 'documentJournal', context: 'manager', path: treeItemPath, - children: FillDocumentJournalItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillDocumentJournalItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('Enum.'): previous.enum.push(GetTreeItem( treeItemId, current.$.name, { icon: 'enum', context: 'manager', path: treeItemPath, - children: FillEnumItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillEnumItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('Report.'): previous.report.push(GetTreeItem( treeItemId, current.$.name, { icon: 'report', context: 'object_and_manager', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('DataProcessor.'): previous.dataProcessor.push(GetTreeItem( treeItemId, current.$.name, { icon: 'dataProcessor', context: 'object_and_manager', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('ChartOfCharacteristicTypes.'): previous.сhartOfCharacteristicTypes.push(GetTreeItem( treeItemId, current.$.name, { icon: 'chartsOfCharacteristicType', context: 'object_and_manager_and_predefined', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('ChartOfAccounts.'): previous.chartOfAccounts.push(GetTreeItem( treeItemId, current.$.name, { icon: 'chartsOfAccount', context: 'object_and_manager_and_predefined', path: treeItemPath, - children: FillChartOfAccountsItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillChartOfAccountsItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('ChartOfCalculationTypes.'): previous.chartOfCalculationTypes.push(GetTreeItem( treeItemId, current.$.name, { icon: 'chartsOfCalculationType', context: 'object_and_manager_and_predefined', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('InformationRegister.'): previous.informationRegister.push(GetTreeItem( treeItemId, current.$.name, { icon: 'informationRegister', context: 'recordset_and_manager', path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillRegisterItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('AccumulationRegister.'): previous.accumulationRegister.push(GetTreeItem( treeItemId, current.$.name, { icon: 'accumulationRegister', context: 'recordset_and_manager', path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillRegisterItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('AccountingRegister.'): previous.accountingRegister.push(GetTreeItem( treeItemId, current.$.name, { icon: 'accountingRegister', context: 'recordset_and_manager', path: treeItemPath, - children: FillRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillRegisterItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('CalculationRegister.'): previous.calculationRegister.push(GetTreeItem( treeItemId, current.$.name, { icon: 'calculationRegister', context: 'recordset_and_manager', path: treeItemPath, - children: FillCalculationRegisterItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillCalculationRegisterItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('BusinessProcess.'): previous.businessProcess.push(GetTreeItem( treeItemId, current.$.name, { icon: 'businessProcess', context: 'object_and_manager', path: treeItemPath, - children: FillObjectItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillObjectItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('Task.'): previous.task.push(GetTreeItem( treeItemId, current.$.name, { icon: 'task', context: 'object_and_manager', path: treeItemPath, - children: FillTaskItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillTaskItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; case current.$.name.startsWith('ExternalDataSource.'): previous.externalDataSource.push(GetTreeItem( treeItemId, current.$.name, { icon: 'externalDataSource', - children: FillExternalDataSourceItemsByMetadata(element.id + '/', current, attributeReduceResult) })); + children: FillExternalDataSourceItemsByMetadata(treeItemIdSlash, current, attributeReduceResult) })); break; } From 48734def95d4099b39bad4de6e26ced9442af28f Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 01:42:51 +0300 Subject: [PATCH 12/16] =?UTF-8?q?=D0=9E=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/metadataView.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/metadataView.ts b/src/metadataView.ts index d00bdfa..7adb0f6 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -106,6 +106,11 @@ export class MetadataView { vscode.workspace.fs.readFile(rootPath.with({ path: fileName })) .then(configXml => { xml2js.parseString(configXml, (err, result) => { + if (err) { + console.error(err); + return; + } + const typedResult = result as PredefinedDataFile; PredefinedDataPanel.show(context.extensionUri, typedResult.PredefinedData); }); @@ -126,6 +131,11 @@ export class MetadataView { vscode.workspace.fs.readFile(rootPath.with({ path: posix.join(element.id, 'ConfigDumpInfo.xml') })) .then(configXml => { xml2js.parseString(configXml, (err, result) => { + if (err) { + console.error(err); + return; + } + const typedResult = result as MetadataFile; CreateTreeElements(element, typedResult); }); @@ -165,11 +175,18 @@ function LoadAndParseConfigurationXml(uri: vscode.Uri) { vscode.workspace.fs.readFile(uri.with({ path: posix.join(fc, 'Configuration.xml') })) .then(configXml => { xml2js.parseString(configXml, (err, result) => { + if (err) { + console.error(err); + return; + } + let synonym = result.MetaDataObject.Configuration[0].Properties[0].Synonym[0]["v8:item"][0]["v8:content"][0]; if (!synonym) { synonym = result.MetaDataObject.Configuration[0].Properties[0].Name[0]; } + console.log(`Конфигурация ${synonym} найдена`); + const treeItem = new TreeItem(fc, `${synonym} (${fc})`, CreateMetadata(fc)); treeItem.contextValue = 'main'; treeItem.path = fc; From bdf480ad072fee5d68e4fac358bd8af9db45f53f Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 01:48:45 +0300 Subject: [PATCH 13/16] =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D1=80=D1=80=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=BD=D0=B0?= =?UTF-8?q?=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B9=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 ++-- package.nls.json | 2 +- package.nls.ru.json | 2 +- src/metadataView.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 339880f..804af60 100644 --- a/package.json +++ b/package.json @@ -151,10 +151,10 @@ { "title": "1C Metadata Viewer", "properties": { - "conf.metadataViewer.configurationSearchDepth": { + "metadataViewer.configurationSearchDepth": { "type": "integer", "default": 3, - "description": "%1c-metadata-viewer.conf.configurationSearchDepth.title%" + "description": "%1c-metadata-viewer.configurationSearchDepth.title%" } } } diff --git a/package.nls.json b/package.nls.json index 5cbafa6..ad8e151 100644 --- a/package.nls.json +++ b/package.nls.json @@ -11,5 +11,5 @@ "1c-metadata-viewer.openValueManagerModule.title": "Open value manager module", "1c-metadata-viewer.openXml.title": "Open XML", "1c-metadata-viewer.openPredefinedData.title": "Open predefined data", - "1c-metadata-viewer.conf.configurationSearchDepth.title": "The number of nesting levels of directories in which 1C:Enterprise configurations are searched" + "1c-metadata-viewer.configurationSearchDepth.title": "The number of nesting levels of directories in which 1C:Enterprise configurations are searched" } \ No newline at end of file diff --git a/package.nls.ru.json b/package.nls.ru.json index cc6cd40..ef6f8ed 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -11,5 +11,5 @@ "1c-metadata-viewer.openValueManagerModule.title": "Открыть модуль менеджера значения", "1c-metadata-viewer.openXml.title": "Открыть XML", "1c-metadata-viewer.openPredefinedData.title": "Открыть предопределенные данные", - "1c-metadata-viewer.conf.configurationSearchDepth.title": "Количество уровней вложенности каталогов в которых осуществляется поиск конфигураций 1С:Предприятия" + "1c-metadata-viewer.configurationSearchDepth.title": "Количество уровней вложенности каталогов в которых осуществляется поиск конфигураций 1С:Предприятия" } \ No newline at end of file diff --git a/src/metadataView.ts b/src/metadataView.ts index 7adb0f6..3f69b90 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -154,7 +154,7 @@ function LoadAndParseConfigurationXml(uri: vscode.Uri) { dot: true, cwd: uri.fsPath, absolute: true, - deep: vscode.workspace.getConfiguration().get('conf.metadataViewer.configurationSearchDepth'), + deep: vscode.workspace.getConfiguration().get('metadataViewer.configurationSearchDepth'), }); console.timeEnd('glob'); From ff81623bac7099dae6481d422de19e33e3ad3d99 Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 01:54:40 +0300 Subject: [PATCH 14/16] README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8775c5e..b6869ac 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Открывает текстовые модули 1С (*.bsl) через контекстное меню у соответствующих элементов. +Функция просмотра предопределенных элементов. + ## Метаданные и модули ### Типы метаданных From bfce89cf4be801be97fa20eb16fba716b2af3e7a Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 10:31:39 +0300 Subject: [PATCH 15/16] =?UTF-8?q?=D0=95=D1=89=D1=91=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=20=D1=81=D0=BC=D0=B5=D0=BD=D0=B8=D0=BB=20=D0=BD=D0=B0=D0=B7?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 ++-- package.nls.json | 2 +- package.nls.ru.json | 2 +- src/metadataView.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 804af60..63d3405 100644 --- a/package.json +++ b/package.json @@ -151,10 +151,10 @@ { "title": "1C Metadata Viewer", "properties": { - "metadataViewer.configurationSearchDepth": { + "metadataViewer.searchDepth": { "type": "integer", "default": 3, - "description": "%1c-metadata-viewer.configurationSearchDepth.title%" + "description": "%1c-metadata-viewer.searchDepth.title%" } } } diff --git a/package.nls.json b/package.nls.json index ad8e151..1a9dab2 100644 --- a/package.nls.json +++ b/package.nls.json @@ -11,5 +11,5 @@ "1c-metadata-viewer.openValueManagerModule.title": "Open value manager module", "1c-metadata-viewer.openXml.title": "Open XML", "1c-metadata-viewer.openPredefinedData.title": "Open predefined data", - "1c-metadata-viewer.configurationSearchDepth.title": "The number of nesting levels of directories in which 1C:Enterprise configurations are searched" + "1c-metadata-viewer.searchDepth.title": "The number of nesting levels of directories in which 1C:Enterprise configurations are searched" } \ No newline at end of file diff --git a/package.nls.ru.json b/package.nls.ru.json index ef6f8ed..d72e622 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -11,5 +11,5 @@ "1c-metadata-viewer.openValueManagerModule.title": "Открыть модуль менеджера значения", "1c-metadata-viewer.openXml.title": "Открыть XML", "1c-metadata-viewer.openPredefinedData.title": "Открыть предопределенные данные", - "1c-metadata-viewer.configurationSearchDepth.title": "Количество уровней вложенности каталогов в которых осуществляется поиск конфигураций 1С:Предприятия" + "1c-metadata-viewer.searchDepth.title": "Количество уровней вложенности каталогов в которых осуществляется поиск конфигураций 1С:Предприятия" } \ No newline at end of file diff --git a/src/metadataView.ts b/src/metadataView.ts index 3f69b90..d6646ed 100644 --- a/src/metadataView.ts +++ b/src/metadataView.ts @@ -154,7 +154,7 @@ function LoadAndParseConfigurationXml(uri: vscode.Uri) { dot: true, cwd: uri.fsPath, absolute: true, - deep: vscode.workspace.getConfiguration().get('metadataViewer.configurationSearchDepth'), + deep: vscode.workspace.getConfiguration().get('metadataViewer.searchDepth'), }); console.timeEnd('glob'); From d709f00476267f5636d71c924fb243700625b57c Mon Sep 17 00:00:00 2001 From: Ilya Bushin Date: Sun, 6 Nov 2022 10:34:52 +0300 Subject: [PATCH 16/16] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=200.?= =?UTF-8?q?0.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 12 ++++++++---- README.md | 12 ++++++------ package.json | 2 +- resources/screenshot.png | Bin 14362 -> 22485 bytes 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1711a7d..ce44ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog -### 0.0.5 +## 0.0.6 + +* [new] Поиск конфигураций 1С во вложенных каталогах и возможность работы с несколькими конфигурациями одновременно + +## 0.0.5 * [new] Просмотр предопределенных элементов * [new] Закончил метаданные верхнего уровня @@ -13,7 +17,7 @@ * Внешние источники данных * [fix] Не открывается модуль формы -### 0.0.4 +## 0.0.4 * [new] Открытие XML * [new] Параметры сеанса, Роли, Общие реквизиты и Планы видов характеристик @@ -23,11 +27,11 @@ * [new] Модуль менеджера для перечислений * [new] Модуль менеджера значения -### 0.0.3 +## 0.0.3 * Добавил регистры сведений и накопления -### 0.0.2 +## 0.0.2 * Добавил реквизиты табличных частей [#1](https://github.com/zerobig/vscode-1c-metadata-viewer/pull/1) * Добавил иконок в дерево метаданных diff --git a/README.md b/README.md index b6869ac..282d17a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Вывод дерева метаданных конфигурации 1С и открытие модулей в VSC -Расширение анализирует файл ConfigDumpInfo.xml выгруженной конфигурации 1С и строит дерево метаданных в панели VS Code. +## Возможности расширения + +* Расширение ищет в открытой папке пары файлов ConfigDumpInfo.xml и Configuration.xml выгруженных конфигураций 1С и для каждой пары строит дерево метаданных в панели VS Code. Для задания глубины просмотра подкаталогов существует настройка "Search Depth". По умолчанию значение настройки равно трём. +* Открывает текстовые модули 1С (*.bsl) через контекстное меню у соответствующих элементов. +* У метаданных для которых есть возможность создания предопределенных элементов можно открыть панель существующих в конфигурации элементов. ![Скриншот дерева метаданных](/resources/screenshot.png) -Открывает текстовые модули 1С (*.bsl) через контекстное меню у соответствующих элементов. - -Функция просмотра предопределенных элементов. - ## Метаданные и модули ### Типы метаданных @@ -50,4 +50,4 @@ * Расширение количества обрабатываемых типов метаданных * Открытие модуля без контекстного меню по двойному щелчку когда модуль у элемента конфигурации один -* Редактирование свойств метаданных в отдельной панели \ No newline at end of file +* Редактирование свойств метаданных в отдельной панели diff --git a/package.json b/package.json index 63d3405..91ce308 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-1c-metadata-viewer", "displayName": "1C Metadata Viewer", "description": "Explore 1C:Enterprise 8 configuration in the usual way", - "version": "0.0.5", + "version": "0.0.6", "publisher": "zerobig", "license": "MIT", "engines": { diff --git a/resources/screenshot.png b/resources/screenshot.png index f5a026e4fe8c99837019df53d2c34269535baf14..0f3a8110acc5fffddf9e972d682a3204abd8d311 100644 GIT binary patch literal 22485 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%0A1LjUGh!u$ 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 ItZC5y0fkEy^Z)<=