From 3ccb61bf1867ab6748b1bb9fe39ee8fcba64d997 Mon Sep 17 00:00:00 2001
From: Joachim Dalen <15696189+joachimdalen@users.noreply.github.com>
Date: Sun, 1 May 2022 15:35:50 +0200
Subject: [PATCH] Implementation (#9)
---
.azext/changelog-cache.json | 4 +
.azext/changelog-config.json | 96 +
.azext/changelog.json | 9 +
.azext/readme.json | 4 +
.ci/build-extension-artifact.template.yml | 90 +
.ci/build.template.yml | 14 +
.ci/create-gh-release.template.yml | 25 +
.ci/install.template.yml | 14 +
.ci/publish-extension.template.yml | 38 +
.ci/run-tests.template.yml | 30 +
.eslintignore | 1 +
.gitignore | 11 +-
.vscode/extensions.json | 7 +
.vscode/settings.json | 32 +
PRIVACY.md | 19 +
README.md | 191 +-
azure-pipelines.yml | 123 +
build-scripts/entry-points.js | 56 +
build-scripts/webpack-script-tags-plugin.js | 17 +
build-scripts/webpack.common.js | 107 +
build-scripts/webpack.config.dev.js | 41 +
build-scripts/webpack.config.prod.js | 16 +
build-scripts/webpack.utils.js | 26 +
docs/CHANGELOG-DEV.md | 26 -
docs/CHANGELOG-PROD.md | 20 -
docs/CHANGELOG.md | 20 -
docs/README-BASE.md | 1 -
docs/README.md | 1 -
extension-icon.png | Bin 3225 -> 4219 bytes
hub-group-icon.png | Bin 0 -> 4917 bytes
marketplace/docs/images/.gitkeep | 0
marketplace/docs/images/panel-preview.png | Bin 0 -> 61595 bytes
marketplace/docs/images/work-hub-preview.png | Bin 0 -> 99933 bytes
marketplace/docs/images/work-item-preview.png | Bin 0 -> 74259 bytes
marketplace/raw/README.md | 58 +
package-lock.json | 16652 ++++++++--------
package.json | 69 +-
.../azdevops-ext-core/DevOpsService.ts | 19 +
.../Common/RestClientBase.ts | 3 +
.../Common/index.ts | 17 +
.../azure-devops-extension-api/Core.ts | 13 +
.../azure-devops-extension-api/Git.ts | 31 +
.../azure-devops-extension-api/Graph.ts | 19 +
.../azure-devops-extension-api/Identities.ts | 3 +
.../azure-devops-extension-api/Wiki.ts | 26 +
.../WorkItemTracking.ts | 94 +
.../WorkItemTrackingProcess.ts | 28 +
.../azure-devops-extension-api/index.ts | 1 +
src/__mocks__/azure-devops-extension-sdk.ts | 176 +
src/__mocks__/styleMock.js | 3 +
src/__tests__/common/chunkUtil.test.ts | 24 +
src/__tests__/common/common.test.tsx | 45 +
.../components/ApproverDisplay.test.tsx | 59 +
.../components/CriteriaTypeDisplay.test.tsx | 21 +
.../common/components/FullStatusTag.test.tsx | 12 +
.../common/components/ProgressBar.test.tsx | 16 +
.../common/components/StatusTag.test.tsx | 17 +
src/__tests__/common/criteriaUtils.test.ts | 71 +
.../common/hooks/useCriteriaId.test.tsx | 28 +
.../common/services/CriteriaService.test.ts | 170 +
.../ConfirmationDialog.test.tsx | 104 +
.../criteria-panel/CriteriaPanel.test.tsx | 228 +
.../CheckListCriteriaSection.test.tsx | 175 +
.../CompletedProcessContainer.test.tsx | 26 +
.../components/CompletionContainer.test.tsx | 47 +
.../components/ProcessingContainer.test.tsx | 32 +
.../RejectionProcessContainer.test.tsx | 32 +
.../ScenarioCriteriaSection.test.tsx | 104 +
.../components/TextCriteriaSection.test.tsx | 37 +
.../view/TextCriteriaViewSection.text.tsx | 21 +
src/admin-hub/AdminPage.tsx | 49 +-
src/admin-hub/components/PageWrapper.tsx | 22 +-
src/admin-hub/index.scss | 10 +-
src/admin-hub/module.json | 8 +
src/admin-hub/module.tsx | 7 +-
src/admin-hub/tabs/AdminConfigurationTab.tsx | 219 +-
src/admin-hub/tabs/AreaConfigurationTab.tsx | 11 -
src/admin-hub/tabs/DocumentTab.tsx | 45 +
.../tabs/orphaned/OrphanedDocumentsTab.tsx | 36 +
.../tabs/OrphanedCriteriaDetailsTab.tsx | 208 +
.../orphaned/tabs/OrphanedCriteriasTab.tsx | 235 +
src/common/DevOpsError.ts | 12 +
src/common/chunkUtil.ts | 4 +
src/common/common.ts | 78 +-
src/common/components/ApproverDisplay.tsx | 47 +
src/common/components/CriteriaTypeDisplay.tsx | 41 +
src/common/components/FullStatusTag.tsx | 17 +
src/common/components/InternalLink.tsx | 15 +
src/common/components/ProgressBar.tsx | 46 +
src/common/components/SlimErrorBoundary.tsx | 54 +
.../components/StatusTag.tsx | 21 +-
src/common/constants.ts | 3 -
src/common/criteriaUtils.ts | 25 +
src/common/errorUtils.ts | 49 +
src/common/hooks/useCriteriaId.tsx | 21 +
src/common/hooks/useDropdownSelection.tsx | 17 -
src/common/localStorage.ts | 28 +
src/common/models/ActionResult.ts | 5 +
src/common/models/CriteriaDocument.ts | 16 -
src/common/models/IAcceptanceCriteria.ts | 27 -
.../services/CriteriaNavigationService.ts | 43 -
src/common/services/CriteriaService.ts | 462 +
src/common/services/StorageService.ts | 238 +-
src/common/services/WorkItemService.ts | 36 -
src/common/types.ts | 125 +
.../ConfirmationDialog.tsx | 98 +
src/confirmation-dialog/index.scss | 4 +
src/confirmation-dialog/module.json | 8 +
src/confirmation-dialog/module.tsx | 9 +
src/control/AcceptanceControl.tsx | 145 -
src/control/AcceptanceControlProvider.ts | 30 -
src/control/azure-devops-theme.ts | 52 -
src/control/common.tsx | 9 -
src/control/components/ActionMenu.tsx | 60 -
src/control/components/CriteriaList.tsx | 146 -
src/control/index.scss | 44 -
src/control/module.tsx | 20 -
src/control/webLogger.ts | 57 -
src/criteria-panel/CriteriaPanel.tsx | 570 +
src/criteria-panel/CriteriaPanelContext.tsx | 83 +
src/criteria-panel/CriteriaPanelData.ts | 60 +
.../components/CheckListCriteriaSection.tsx | 141 +
.../components/CompletedProcessContainer.tsx | 36 +
.../components/CompletionContainer.tsx | 50 +
.../components/InternalTagPicker.tsx | 75 +
.../components/ProcessingContainer.tsx | 49 +
.../components/RejectionProcessContainer.tsx | 48 +
.../components/ScenarioCriteriaSection.tsx | 176 +
.../components/TextCriteriaSection.tsx | 46 +
.../view/ChecklistCriteriaViewSection.tsx | 57 +
.../view/ScenarioCriteriaViewSection.tsx | 51 +
.../view/TextCriteriaViewSection.tsx | 19 +
src/criteria-panel/index.scss | 16 +
src/criteria-panel/module.json | 8 +
src/criteria-panel/module.tsx | 14 +
src/panel/index.scss | 2 -
src/panel/module.tsx | 158 -
src/progress-control/ProgressControl.tsx | 98 +
.../common/ProgressControlService.ts | 64 +
src/progress-control/index.scss | 5 +
src/progress-control/module.json | 8 +
src/progress-control/module.tsx | 10 +
src/setupTests.ts | 5 +
src/styles/_common.scss | 91 +
src/styles/_criteria-list.scss | 10 +
src/styles/mixins.scss | 16 -
src/testdata.ts | 52 +
src/wi-control/AcceptanceControl.tsx | 347 +
src/wi-control/components/CriteriaView.tsx | 322 +
src/wi-control/index.scss | 26 +
src/wi-control/module.json | 8 +
.../index.tsx => wi-control/module.tsx} | 4 +-
src/work-hub/ColumnsPanel.tsx | 23 +
src/work-hub/WorkHub.tsx | 418 +
src/work-hub/assets/hub-icon-dark.png | Bin 0 -> 2383 bytes
src/work-hub/assets/hub-icon-light.png | Bin 0 -> 3228 bytes
src/work-hub/components/CriteriaTree.tsx | 310 +
src/work-hub/components/CriteriaTreeData.tsx | 297 +
src/work-hub/components/HubFilterBar.tsx | 163 +
src/work-hub/components/SettingContainer.tsx | 50 +
src/work-hub/components/WorkItemTypeTag.tsx | 35 +
src/work-hub/index.scss | 15 +-
src/work-hub/module.json | 8 +
src/work-hub/module.tsx | 19 +-
src/work-hub/settings-panel/SettingsPanel.tsx | 75 +
.../tabs/NotificationsGeneralTab.tsx | 51 +
.../tabs/WorkItemDisplayTab.tsx | 33 +
vss-extension.dev.json | 231 +
vss-extension.prod.json | 220 +
vss-extension.qa.json | 221 +
170 files changed, 18286 insertions(+), 9090 deletions(-)
create mode 100644 .azext/changelog-cache.json
create mode 100644 .azext/changelog-config.json
create mode 100644 .azext/changelog.json
create mode 100644 .azext/readme.json
create mode 100644 .ci/build-extension-artifact.template.yml
create mode 100644 .ci/build.template.yml
create mode 100644 .ci/create-gh-release.template.yml
create mode 100644 .ci/install.template.yml
create mode 100644 .ci/publish-extension.template.yml
create mode 100644 .ci/run-tests.template.yml
create mode 100644 .vscode/extensions.json
create mode 100644 .vscode/settings.json
create mode 100644 PRIVACY.md
create mode 100644 azure-pipelines.yml
create mode 100644 build-scripts/entry-points.js
create mode 100644 build-scripts/webpack-script-tags-plugin.js
create mode 100644 build-scripts/webpack.common.js
create mode 100644 build-scripts/webpack.config.dev.js
create mode 100644 build-scripts/webpack.config.prod.js
create mode 100644 build-scripts/webpack.utils.js
delete mode 100644 docs/CHANGELOG-DEV.md
delete mode 100644 docs/CHANGELOG-PROD.md
delete mode 100644 docs/CHANGELOG.md
delete mode 100644 docs/README-BASE.md
delete mode 100644 docs/README.md
create mode 100644 hub-group-icon.png
create mode 100644 marketplace/docs/images/.gitkeep
create mode 100644 marketplace/docs/images/panel-preview.png
create mode 100644 marketplace/docs/images/work-hub-preview.png
create mode 100644 marketplace/docs/images/work-item-preview.png
create mode 100644 marketplace/raw/README.md
create mode 100644 src/__mocks__/@joachimdalen/azdevops-ext-core/DevOpsService.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Common/RestClientBase.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Common/index.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Core.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Git.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Graph.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Identities.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/Wiki.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/WorkItemTracking.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/WorkItemTrackingProcess.ts
create mode 100644 src/__mocks__/azure-devops-extension-api/index.ts
create mode 100644 src/__mocks__/azure-devops-extension-sdk.ts
create mode 100644 src/__mocks__/styleMock.js
create mode 100644 src/__tests__/common/chunkUtil.test.ts
create mode 100644 src/__tests__/common/common.test.tsx
create mode 100644 src/__tests__/common/components/ApproverDisplay.test.tsx
create mode 100644 src/__tests__/common/components/CriteriaTypeDisplay.test.tsx
create mode 100644 src/__tests__/common/components/FullStatusTag.test.tsx
create mode 100644 src/__tests__/common/components/ProgressBar.test.tsx
create mode 100644 src/__tests__/common/components/StatusTag.test.tsx
create mode 100644 src/__tests__/common/criteriaUtils.test.ts
create mode 100644 src/__tests__/common/hooks/useCriteriaId.test.tsx
create mode 100644 src/__tests__/common/services/CriteriaService.test.ts
create mode 100644 src/__tests__/confirmation-dialog/ConfirmationDialog.test.tsx
create mode 100644 src/__tests__/criteria-panel/CriteriaPanel.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/CheckListCriteriaSection.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/CompletedProcessContainer.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/CompletionContainer.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/ProcessingContainer.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/RejectionProcessContainer.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/ScenarioCriteriaSection.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/TextCriteriaSection.test.tsx
create mode 100644 src/__tests__/criteria-panel/components/view/TextCriteriaViewSection.text.tsx
create mode 100644 src/admin-hub/module.json
delete mode 100644 src/admin-hub/tabs/AreaConfigurationTab.tsx
create mode 100644 src/admin-hub/tabs/DocumentTab.tsx
create mode 100644 src/admin-hub/tabs/orphaned/OrphanedDocumentsTab.tsx
create mode 100644 src/admin-hub/tabs/orphaned/tabs/OrphanedCriteriaDetailsTab.tsx
create mode 100644 src/admin-hub/tabs/orphaned/tabs/OrphanedCriteriasTab.tsx
create mode 100644 src/common/DevOpsError.ts
create mode 100644 src/common/chunkUtil.ts
create mode 100644 src/common/components/ApproverDisplay.tsx
create mode 100644 src/common/components/CriteriaTypeDisplay.tsx
create mode 100644 src/common/components/FullStatusTag.tsx
create mode 100644 src/common/components/InternalLink.tsx
create mode 100644 src/common/components/ProgressBar.tsx
create mode 100644 src/common/components/SlimErrorBoundary.tsx
rename src/{control => common}/components/StatusTag.tsx (50%)
delete mode 100644 src/common/constants.ts
create mode 100644 src/common/criteriaUtils.ts
create mode 100644 src/common/errorUtils.ts
create mode 100644 src/common/hooks/useCriteriaId.tsx
delete mode 100644 src/common/hooks/useDropdownSelection.tsx
create mode 100644 src/common/localStorage.ts
create mode 100644 src/common/models/ActionResult.ts
delete mode 100644 src/common/models/CriteriaDocument.ts
delete mode 100644 src/common/models/IAcceptanceCriteria.ts
delete mode 100644 src/common/services/CriteriaNavigationService.ts
create mode 100644 src/common/services/CriteriaService.ts
delete mode 100644 src/common/services/WorkItemService.ts
create mode 100644 src/common/types.ts
create mode 100644 src/confirmation-dialog/ConfirmationDialog.tsx
create mode 100644 src/confirmation-dialog/index.scss
create mode 100644 src/confirmation-dialog/module.json
create mode 100644 src/confirmation-dialog/module.tsx
delete mode 100644 src/control/AcceptanceControl.tsx
delete mode 100644 src/control/AcceptanceControlProvider.ts
delete mode 100644 src/control/azure-devops-theme.ts
delete mode 100644 src/control/common.tsx
delete mode 100644 src/control/components/ActionMenu.tsx
delete mode 100644 src/control/components/CriteriaList.tsx
delete mode 100644 src/control/index.scss
delete mode 100644 src/control/module.tsx
delete mode 100644 src/control/webLogger.ts
create mode 100644 src/criteria-panel/CriteriaPanel.tsx
create mode 100644 src/criteria-panel/CriteriaPanelContext.tsx
create mode 100644 src/criteria-panel/CriteriaPanelData.ts
create mode 100644 src/criteria-panel/components/CheckListCriteriaSection.tsx
create mode 100644 src/criteria-panel/components/CompletedProcessContainer.tsx
create mode 100644 src/criteria-panel/components/CompletionContainer.tsx
create mode 100644 src/criteria-panel/components/InternalTagPicker.tsx
create mode 100644 src/criteria-panel/components/ProcessingContainer.tsx
create mode 100644 src/criteria-panel/components/RejectionProcessContainer.tsx
create mode 100644 src/criteria-panel/components/ScenarioCriteriaSection.tsx
create mode 100644 src/criteria-panel/components/TextCriteriaSection.tsx
create mode 100644 src/criteria-panel/components/view/ChecklistCriteriaViewSection.tsx
create mode 100644 src/criteria-panel/components/view/ScenarioCriteriaViewSection.tsx
create mode 100644 src/criteria-panel/components/view/TextCriteriaViewSection.tsx
create mode 100644 src/criteria-panel/index.scss
create mode 100644 src/criteria-panel/module.json
create mode 100644 src/criteria-panel/module.tsx
delete mode 100644 src/panel/index.scss
delete mode 100644 src/panel/module.tsx
create mode 100644 src/progress-control/ProgressControl.tsx
create mode 100644 src/progress-control/common/ProgressControlService.ts
create mode 100644 src/progress-control/index.scss
create mode 100644 src/progress-control/module.json
create mode 100644 src/progress-control/module.tsx
create mode 100644 src/setupTests.ts
create mode 100644 src/styles/_common.scss
create mode 100644 src/styles/_criteria-list.scss
delete mode 100644 src/styles/mixins.scss
create mode 100644 src/testdata.ts
create mode 100644 src/wi-control/AcceptanceControl.tsx
create mode 100644 src/wi-control/components/CriteriaView.tsx
create mode 100644 src/wi-control/index.scss
create mode 100644 src/wi-control/module.json
rename src/{control/index.tsx => wi-control/module.tsx} (59%)
create mode 100644 src/work-hub/ColumnsPanel.tsx
create mode 100644 src/work-hub/WorkHub.tsx
create mode 100644 src/work-hub/assets/hub-icon-dark.png
create mode 100644 src/work-hub/assets/hub-icon-light.png
create mode 100644 src/work-hub/components/CriteriaTree.tsx
create mode 100644 src/work-hub/components/CriteriaTreeData.tsx
create mode 100644 src/work-hub/components/HubFilterBar.tsx
create mode 100644 src/work-hub/components/SettingContainer.tsx
create mode 100644 src/work-hub/components/WorkItemTypeTag.tsx
create mode 100644 src/work-hub/module.json
create mode 100644 src/work-hub/settings-panel/SettingsPanel.tsx
create mode 100644 src/work-hub/settings-panel/tabs/NotificationsGeneralTab.tsx
create mode 100644 src/work-hub/settings-panel/tabs/WorkItemDisplayTab.tsx
create mode 100644 vss-extension.dev.json
create mode 100644 vss-extension.prod.json
create mode 100644 vss-extension.qa.json
diff --git a/.azext/changelog-cache.json b/.azext/changelog-cache.json
new file mode 100644
index 0000000..7ead9ea
--- /dev/null
+++ b/.azext/changelog-cache.json
@@ -0,0 +1,4 @@
+{
+ "issues": [],
+ "pullRequests": []
+}
\ No newline at end of file
diff --git a/.azext/changelog-config.json b/.azext/changelog-config.json
new file mode 100644
index 0000000..5c58447
--- /dev/null
+++ b/.azext/changelog-config.json
@@ -0,0 +1,96 @@
+{
+ "repository": "joachimdalen/azdevops-acceptance-criterias",
+ "changelogTitle": {
+ "size": "h1",
+ "format": "Changelog"
+ },
+ "releaseTitleFormat": {
+ "size": "h2",
+ "format": "{{version}} ({{publishDate}})"
+ },
+ "moduleTitleFormat": {
+ "size": "h4",
+ "format": "`{{name}}@{{version}}`"
+ },
+ "moduleChangesTitle": {
+ "size": "h2",
+ "format": ":package: Module changes"
+ },
+ "sectionSplitter": "---",
+ "typeSize": "h3",
+ "typeMapping": {
+ "feature": ":rocket: Features ({{changeCount}})",
+ "fix": ":bug: Fixes ({{changeCount}})",
+ "tests": ":test_tube: Tests ({{changeCount}})",
+ "other": ":speech_balloon: Other ({{changeCount}})",
+ "docs": ":memo: Documentation ({{changeCount}})",
+ "maint": ":hammer_and_wrench: Maintenance ({{changeCount}})"
+ },
+ "sections": {
+ "summary": {
+ "title": {
+ "size": "bold",
+ "format": ":pencil2: Release summary"
+ }
+ },
+ "knownIssues": {
+ "title": {
+ "size": "bold",
+ "format": ":bulb: Known issues"
+ }
+ },
+ "breakingChanges": {
+ "title": {
+ "size": "bold",
+ "format": ":fire: BREAKING CHANGES :fire:"
+ }
+ }
+ },
+ "typeResourcePrefixMapping": {
+ "feature": {
+ "issue": "Suggested in",
+ "pullRequest": "Added in"
+ },
+ "fix": {
+ "issue": "Reported in",
+ "pullRequest": "Fixed in"
+ },
+ "docs": {
+ "issue": "Changed needed",
+ "pullRequest": "Changed in"
+ },
+ "maint": {
+ "pullRequest": "Changed in"
+ },
+ "enhancement": {
+ "issue": "Suggested in",
+ "pullRequest": "Improved in"
+ }
+ },
+ "attributionTitleFormat": {
+ "size": "h2",
+ "format": ":star2: Contributors"
+ },
+ "attributionSubTitle": {
+ "format": "Thank you to the following for contributing to the latest release"
+ },
+ "attributionLinkTextFormat": {
+ "format": "@{{ghUsername}}"
+ },
+ "knownAuthors": ["joachimdalen"],
+ "useDescriptiveIssues": true,
+ "useDescriptivePullRequests": true,
+ "replaceEmojis": {
+ "types": true,
+ "changelogTitle": true,
+ "releaseTitle": true,
+ "moduleTitle": true,
+ "attributionTitle": true,
+ "attributionSubTitle": true,
+ "moduleChangesTitle": true,
+ "githubIssues": false,
+ "githubPullRequests": false,
+ "sectionTitle": true,
+ "sectionContent": true
+ }
+}
diff --git a/.azext/changelog.json b/.azext/changelog.json
new file mode 100644
index 0000000..0d8e01b
--- /dev/null
+++ b/.azext/changelog.json
@@ -0,0 +1,9 @@
+[
+ {
+ "publishDate": "02-05-2022",
+ "version": "1.0.0",
+ "sections": {
+ "summary": [{ "type": "text", "content": "Initial release" }]
+ }
+ }
+]
diff --git a/.azext/readme.json b/.azext/readme.json
new file mode 100644
index 0000000..ce1995a
--- /dev/null
+++ b/.azext/readme.json
@@ -0,0 +1,4 @@
+{
+ "partials": {}
+ }
+
\ No newline at end of file
diff --git a/.ci/build-extension-artifact.template.yml b/.ci/build-extension-artifact.template.yml
new file mode 100644
index 0000000..e0ce711
--- /dev/null
+++ b/.ci/build-extension-artifact.template.yml
@@ -0,0 +1,90 @@
+parameters:
+ - name: artifact
+ default: extension
+ - name: extensionEnv
+ default: dev
+ values:
+ - dev
+ - qa
+ - prod
+ - name: taskVersion
+ displayName: 'Task Version'
+ type: string
+ default: $(Task.Extension.Version)
+ - name: generateVersionChangelog
+ type: boolean
+ default: true
+jobs:
+ - job:
+ steps:
+ - task: TfxInstaller@3
+ displayName: 'Install Tfx'
+ inputs:
+ version: 'v0.10.0'
+ - task: QueryAzureDevOpsExtensionVersion@3
+ displayName: 'Query existing version'
+ inputs:
+ connectTo: 'VsTeam'
+ connectedServiceName: $(marketplaceServiceConnection)
+ publisherId: '$(PublisherID)'
+ extensionId: '$(ExtensionID)'
+ versionAction: 'Patch'
+ outputVariable: 'Task.Extension.Version'
+ - template: install.template.yml
+ - template: build.template.yml
+ parameters:
+ extensionEnv: ${{ parameters.extensionEnv }}
+ - task: Npm@1
+ displayName: 'Build changelog'
+ inputs:
+ command: custom
+ customCommand: run changelog:prod
+ - task: Npm@1
+ displayName: 'Build single version changelog'
+ condition: eq(${{ parameters.generateVersionChangelog }}, true)
+ inputs:
+ command: custom
+ customCommand: run changelog:prod:version -- --version ${{ parameters.taskVersion }}
+ - task: Npm@1
+ displayName: 'Build readme'
+ inputs:
+ command: custom
+ customCommand: run docs:readme
+ - task: PackageAzureDevOpsExtension@3
+ displayName: 'Package extension'
+ inputs:
+ rootFolder: '$(Build.SourcesDirectory)'
+ patternManifest: 'vss-extension.${{ parameters.extensionEnv }}.json'
+ updateTasksVersion: false
+ extensionVersion: ${{ parameters.taskVersion }}
+ - task: Bash@3
+ displayName: 'Move artifacts'
+ inputs:
+ targetType: inline
+ workingDirectory:
+ script: |
+ mkdir $(Build.ArtifactStagingDirectory)/extension/
+ mkdir $(Build.ArtifactStagingDirectory)/changelog/
+ mv $(Build.SourcesDirectory)/*.vsix $(Build.ArtifactStagingDirectory)/extension/
+ cp $(Build.SourcesDirectory)/marketplace/docs/CHANGELOG.md $(Build.ArtifactStagingDirectory)/changelog/
+ - task: Bash@3
+ displayName: 'Move version changelog'
+ condition: eq(${{ parameters.generateVersionChangelog }}, true)
+ inputs:
+ targetType: inline
+ workingDirectory:
+ script: |
+ mv $(Build.SourcesDirectory)/marketplace/docs/CHANGELOG-RELEASE.md $(Build.ArtifactStagingDirectory)/changelog/
+ - task: PublishPipelineArtifact@1
+ displayName: 'Publish ${{ parameters.artifact }} artifacts'
+ inputs:
+ targetPath: '$(Build.ArtifactStagingDirectory)/extension'
+ artifactName: '${{ parameters.artifact }}'
+ publishLocation: pipeline
+ - task: PublishPipelineArtifact@1
+ displayName: 'Publish changelog artifacts'
+ inputs:
+ targetPath: '$(Build.ArtifactStagingDirectory)/changelog'
+ artifactName: 'changelog'
+ publishLocation: pipeline
+
\ No newline at end of file
diff --git a/.ci/build.template.yml b/.ci/build.template.yml
new file mode 100644
index 0000000..411989c
--- /dev/null
+++ b/.ci/build.template.yml
@@ -0,0 +1,14 @@
+parameters:
+ - name: extensionEnv
+ default: dev
+ values:
+ - dev
+ - qa
+ - prod
+
+steps:
+ - task: Npm@1
+ displayName: 'Compile - ${{ parameters.extensionEnv }}'
+ inputs:
+ command: custom
+ customCommand: 'run compile:${{ parameters.extensionEnv }}'
diff --git a/.ci/create-gh-release.template.yml b/.ci/create-gh-release.template.yml
new file mode 100644
index 0000000..c8e3eed
--- /dev/null
+++ b/.ci/create-gh-release.template.yml
@@ -0,0 +1,25 @@
+parameters:
+ - name: version
+ type: string
+ - name: isPreview
+ type: boolean
+ default: false
+
+steps:
+ - checkout: none
+ - download: none
+ - download: 'current'
+ displayName: 'Download changelog'
+ artifact: 'changelog'
+ - task: GitHubRelease@1
+ displayName: 'Create GitHub Release'
+ inputs:
+ gitHubConnection: github-azdevops-extensions
+ repositoryName: joachimdalen/azdevops-acceptance-criterias
+ tagSource: userSpecifiedTag
+ tag: v${{ parameters.version }}
+ title: 'v${{ parameters.version }}: Update'
+ addChangeLog: false
+ isPreRelease: ${{ parameters.isPreview }}
+ releaseNotesSource: filePath
+ releaseNotesFilePath: $(Pipeline.Workspace)/changelog/v${{ parameters.version }}.md
diff --git a/.ci/install.template.yml b/.ci/install.template.yml
new file mode 100644
index 0000000..d9c258b
--- /dev/null
+++ b/.ci/install.template.yml
@@ -0,0 +1,14 @@
+steps:
+ - task: NodeTool@0
+ displayName: 'Install node'
+ inputs:
+ versionSpec: '16.x'
+ - task: Cache@2
+ displayName: Cache npm
+ inputs:
+ key: 'npm | "$(Agent.OS)" | $(Build.SourcesDirectory)/package-lock.json'
+ path: "$(npm_config_cache)"
+ - task: Npm@1
+ displayName: 'Install dependencies'
+ inputs:
+ command: ci
\ No newline at end of file
diff --git a/.ci/publish-extension.template.yml b/.ci/publish-extension.template.yml
new file mode 100644
index 0000000..2a828e4
--- /dev/null
+++ b/.ci/publish-extension.template.yml
@@ -0,0 +1,38 @@
+parameters:
+ - name: pipelineEnv
+ - name: artifact
+ default: extension
+ - name: extensionVisibility
+ type: string
+ default: private
+ values:
+ - default
+ - private
+ - private_preview
+ - public
+ - public_preview
+jobs:
+ - deployment:
+ displayName: 'Publish Extension'
+ environment: ${{ parameters.pipelineEnv }}
+ strategy:
+ runOnce:
+ deploy:
+ steps:
+ - download: none
+ - download: 'current'
+ displayName: 'Download extension'
+ artifact: ${{ parameters.artifact }}
+ - task: TfxInstaller@3
+ displayName: 'Install Tfx'
+ inputs:
+ version: 'v0.10.0'
+ - task: PublishAzureDevOpsExtension@3
+ displayName: "Publish to Marketplace"
+ inputs:
+ connectTo: 'VsTeam'
+ connectedServiceName: 'marketplace-joachim-dalen'
+ fileType: 'vsix'
+ vsixFile: '$(Pipeline.Workspace)/**/*.vsix'
+ updateTasksVersion: false
+ extensionVisibility: ${{ parameters.extensionVisibility }}
diff --git a/.ci/run-tests.template.yml b/.ci/run-tests.template.yml
new file mode 100644
index 0000000..840ecc6
--- /dev/null
+++ b/.ci/run-tests.template.yml
@@ -0,0 +1,30 @@
+steps:
+ - task: Npm@1
+ displayName: 'Run tests'
+ inputs:
+ command: custom
+ customCommand: 'run test:coverage'
+ - task: Bash@3
+ displayName: 'Move cover files'
+ inputs:
+ targetType: 'inline'
+ script: |
+ cp -r $(Build.SourcesDirectory)/coverage $(Build.ArtifactStagingDirectory)
+ - task: Bash@3
+ displayName: 'Move report'
+ inputs:
+ targetType: 'inline'
+ script: |
+ mkdir $(Build.ArtifactStagingDirectory)/reports
+ cp $(Build.SourcesDirectory)/test-results.xml $(Build.ArtifactStagingDirectory)/reports/test-results.xml
+ - task: PublishTestResults@2
+ displayName: 'Publish test results'
+ inputs:
+ testResultsFormat: 'JUnit'
+ testResultsFiles: '$(Build.ArtifactStagingDirectory)/reports/test-results.xml'
+ - task: PublishCodeCoverageResults@1
+ displayName: 'Publish coverage'
+ inputs:
+ codeCoverageTool: 'Cobertura'
+ summaryFileLocation: '$(Build.ArtifactStagingDirectory)/coverage/cobertura-coverage.xml'
+ pathToSources: '$(Build.SourcesDirectory)/src'
diff --git a/.eslintignore b/.eslintignore
index a902f5f..bb1ec9a 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -5,3 +5,4 @@ webpack.config.js
ci/**
docs/**
marketplace/**
+**/__mocks__/**
diff --git a/.gitignore b/.gitignore
index cf64c49..5603c47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,8 +63,9 @@ coverage
.nyc*
!ci/buildDocs.js
-
-src/tasks/npm*
-src/common/audit*
-src/docs/README.md
-src/docs/CHANGELOG.md
+docs/README.md
+docs/CHANGELOG*.md
+test-results.xml
+!*webpack*.js
+!src/__mocks__/*.js
+!build-scripts/*.js
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..60752e8
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ "recommendations": [
+ "esbenp.prettier-vscode",
+ "dbaeumer.vscode-eslint",
+ "ms-azure-devops.azure-pipelines"
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..31bc550
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,32 @@
+{
+ "json.schemas": [
+ {
+ "fileMatch": [
+ "/.azext/changelog-prod.json"
+ ],
+ "url": "https://raw.githubusercontent.com/joachimdalen/azext/master/schemas/v1/changelog-schema.json"
+ },
+ {
+ "fileMatch": [
+ "/.azext/mapping.json"
+ ],
+ "url": "https://raw.githubusercontent.com/joachimdalen/azext/master/schemas/v1/mapping-schema.json"
+ },
+ {
+ "fileMatch": [
+ "/.azext/readme.json"
+ ],
+ "url": "https://raw.githubusercontent.com/joachimdalen/azext/master/schemas/v1/readme-schema.json"
+ }
+ ],
+ "[azure-pipelines]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[markdown]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "files.associations": {
+ "azure-pipelines.yml": "azure-pipelines",
+ "**/.ci/**/*.yml": "azure-pipelines"
+ },
+}
\ No newline at end of file
diff --git a/PRIVACY.md b/PRIVACY.md
new file mode 100644
index 0000000..f0f90a8
--- /dev/null
+++ b/PRIVACY.md
@@ -0,0 +1,19 @@
+# Privacy Policy
+
+This document serves as the privacy policy for the following extensions published under the publisher JoachimDalen
+
+- Acceptance Criterias
+
+## Security of information
+
+All information/data processed in the extensions is contained within your Azure DevOps environment and accessed using the availeble information on the pipeline agent, or using the offical Azure DevOps REST apis. No information is sent outside of these sources.
+
+## Collection and use of your personal information
+
+I respect the wish for privacy, therefore none of my extensions contains any tracking on usage or issues. Based on this I am dependent on bug reports and discussions to be able to solve any issues and improve the extensions.
+
+## Contact
+
+If you have any questions, please submit an issue on the [GitHub repository](https://github.com/joachimdalen/azdevops-acceptance-criterias).
+
+> This privacy policy was last updated on December 22nd, 2021.
diff --git a/README.md b/README.md
index 3139678..b951b47 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,190 @@
-# Adcanced Acceptance Criterias
+
+
+
+
+
+
+
+
+
+
+ Table of Contents
+
+ -
+ About The Project
+
+
+ - Post Install Activation
+ -
+ Getting Started
+
+
+ - Usage
+ - Roadmap
+ - Contributing
+ - Release and merge strategy
+ - License
+ - Contact
+
+
+
+
+
+---
+
+## About The Project
+
+TODO
+
+## Getting Started
+
+### Prerequisites
+
+- A MarketPlace publisher [Create a publisher](https://docs.microsoft.com/en-us/azure/devops/extend/publish/overview?view=azure-devops#create-a-publisher)
+- `tfx-cli` installed. Due to issues with outdated dependencies this is not included in `package.json`
+
+ ```sh
+ npm install -g tfx-cli
+ ```
+
+- Pipelines uses the following extensions that needs to be installed in your organization in addition to default tasks:
+ - [GitGuard](https://marketplace.visualstudio.com/items?itemName=joachimdalen.gitguard) - Used to verify changes to files, such as changelog.
+ - [Azure DevOps Extension Tasks](https://marketplace.visualstudio.com/items?itemName=ms-devlabs.vsts-developer-tools-build-tasks) - Used to build and publish extension.
+
+### Installation
+
+1. Clone the repo
+
+ ```sh
+ git clone https://github.com/joachimdalen/azdevops-acceptance-criterias.git
+ ```
+
+2. Install dependencies
+
+ ```sh
+ > npm install
+ ```
+
+3. Update publisher in `vss-extension.dev.json`
+4. Compile development version
+
+ ```sh
+ npm run prepare:dev
+ ```
+
+5. [Publish extension](https://docs.microsoft.com/en-us/azure/devops/extend/publish/overview?view=azure-devops#publish-an-extension)
+6. [Share](https://docs.microsoft.com/en-us/azure/devops/extend/publish/overview?view=azure-devops#share-an-extension) and [install](https://docs.microsoft.com/en-us/azure/devops/extend/publish/overview?view=azure-devops#install-an-extension) extension
+7. Run extension
+
+ ```sh
+ npm run serve:dev
+ ```
+
+ **Note:** You might need to open [https://localhost:3000/](https://localhost:3000/) in your browser from time to time to accept the unsecure certificate to have the extension load properly from your local environment.
+
+(back to top)
+
+
+
+## Usage
+
+See [documenation](./docs/index.md) for rule usage.
+
+(back to top)
+
+
+
+## Roadmap
+
+See the [open issues](https://github.com/joachimdalen/azdevops-acceptance-criterias/issues?q=is%3Aopen+is%3Aissue+label%3A%40type%2Ffeature) for a full list of proposed features.
+
+(back to top)
+
+
+
+## Contributing
+
+Contributions are welcome, both in the form of suggestions and code. Create
+
+If you want to contribute code, I ask that you follow some guidelines.
+
+- New and changed features should to the best ability be covered by tests
+- Follow the branching policy:
+ - `feature/` for new features
+ - `bugfix/` for bug fixes
+ - `docs/` for documentation changes
+- If your change is related to an issue, use the id as the first part of the branch e.g `bugfix/12-fix-crash-when-updating-rule`
+- Pull requests should target the `develop` branch
+
+1. Fork the Project
+2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
+3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
+4. Push to the Branch (`git push origin feature/AmazingFeature`)
+5. Open a Pull Request
+
+(back to top)
+
+## Release and merge strategy
+
+- `master` is only deployed to `PROD` and tagged with `v`
+ - Pull requests are always squash merged into `master`
+ - `master` is the only branch where GitHub releases are created for
+- `feature/*` and `bugfix/*` are deployed to `QA`. For deployment to `DEV` using local assets (only manifest changes are deployed to dev), the `Deploy to DEV instead of QA` option needs to be checked when running the deployment pipeline.
+
+`QA` and `DEV` are private development and verfication environments (publications of the extensions.) Submit a new issue if you for some reason wish access to either of these.
+
+**Note** Access to these are not given for your local development. Please publish your own development release.
+
+
+
+## License
+
+Distributed under the MIT License. See `LICENSE` for more information.
+
+(back to top)
+
+
+
+## Contact
+
+If you have generic questions about the project or usage you can make contact in the following ways:
+
+- Submit an issue with the `@type/question` label - [New Issue](https://github.com/joachimdalen/azdevops-acceptance-criterias/issues/new)
+- Submit a new question under the [Marketplace Q&A section](https://marketplace.visualstudio.com/items?itemName=joachimdalen.acceptance-criterias&ssr=false#qna).
+
+(back to top)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644
index 0000000..fa9e3b2
--- /dev/null
+++ b/azure-pipelines.yml
@@ -0,0 +1,123 @@
+parameters:
+ - name: taskVersion
+ displayName: 'Task Version'
+ type: string
+ default: $(Task.Extension.Version)
+ - name: deployToDev
+ displayName: 'Deploy to DEV instead of QA'
+ type: boolean
+ default: false
+
+trigger:
+ branches:
+ include:
+ - master
+ paths:
+ exclude:
+ - .github/*
+ - .azext/*
+ - .vscode/*
+ - .ci/*
+ - docs/*
+pr: none
+pool:
+ vmImage: ubuntu-latest
+
+variables:
+ npm_config_cache: $(Pipeline.Workspace)/.npm
+ isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
+ marketplaceServiceConnection: 'marketplace-joachim-dalen'
+
+stages:
+ - stage: 'run_tests'
+ displayName: Test & Build
+ jobs:
+ - job:
+ steps:
+ - template: .ci/install.template.yml
+ - template: .ci/run-tests.template.yml
+
+ - stage: package_dev
+ displayName: '[DEV] Package'
+ dependsOn: 'run_tests'
+ condition: and(succeeded(), eq(${{ parameters.deployToDev }}, true), eq(variables.isMain, false))
+ variables:
+ - group: 'mp-acceptance-criterias-dev'
+ jobs:
+ - template: .ci/build-extension-artifact.template.yml
+ parameters:
+ extensionEnv: dev
+ taskVersion: ${{ parameters.taskVersion }}
+ generateVersionChangelog: false
+
+ - stage: publish_dev
+ displayName: '[DEV] Publish'
+ dependsOn: 'package_dev'
+ condition: and(succeeded(), eq(${{ parameters.deployToDev }}, true), eq(variables.isMain, false))
+ variables:
+ - group: 'mp-acceptance-criterias-dev'
+ jobs:
+ - template: .ci/publish-extension.template.yml
+ parameters:
+ pipelineEnv: acceptance-criterias-dev-env
+ extensionVisibility: private_preview
+
+ - stage: package_qa
+ displayName: '[QA] Package'
+ dependsOn: 'run_tests'
+ condition: and(succeeded(), eq(${{ parameters.deployToDev }}, false), eq(variables.isMain, false))
+ variables:
+ - group: 'mp-acceptance-criterias-qa'
+ jobs:
+ - template: .ci/build-extension-artifact.template.yml
+ parameters:
+ extensionEnv: qa
+ taskVersion: ${{ parameters.taskVersion }}
+ generateVersionChangelog: false
+
+ - stage: publish_qa
+ displayName: '[QA] Publish'
+ dependsOn: 'package_qa'
+ condition: and(succeeded(), eq(${{ parameters.deployToDev }}, false), eq(variables.isMain, false))
+ variables:
+ - group: 'mp-acceptance-criterias-qa'
+ jobs:
+ - template: .ci/publish-extension.template.yml
+ parameters:
+ pipelineEnv: acceptance-criterias-qa-env
+ extensionVisibility: private_preview
+
+ - stage: package_prod
+ displayName: '[PROD] Package'
+ dependsOn: 'run_tests'
+ condition: and(succeeded(), eq(variables.isMain, true))
+ variables:
+ - group: 'mp-acceptance-criterias-prod'
+ jobs:
+ - job: verify_changelog
+ steps:
+ - task: GitGuardChanges@0
+ displayName: '[PROD] Verify changelog'
+ inputs:
+ sourceCommitHash: 'tag:v*[!-qa]'
+ matchPattern: '.azext/changelog.json'
+ targetCommitHash: 'HEAD'
+ matchStrategy: 'single'
+ changed: true
+ breakOnFailure: true
+ - template: .ci/build-extension-artifact.template.yml
+ parameters:
+ extensionEnv: prod
+ taskVersion: ${{ parameters.taskVersion }}
+
+ - stage: publish_prod
+ displayName: '[PROD] Publish'
+ dependsOn: 'package_prod'
+ condition: and(succeeded(), eq(variables.isMain, true))
+ variables:
+ - group: 'mp-acceptance-criterias-prod'
+ jobs:
+ - template: .ci/publish-extension.template.yml
+ parameters:
+ pipelineEnv: acceptance-criterias-prod-env
+ extensionVisibility: public_preview
diff --git a/build-scripts/entry-points.js b/build-scripts/entry-points.js
new file mode 100644
index 0000000..d6eab9e
--- /dev/null
+++ b/build-scripts/entry-points.js
@@ -0,0 +1,56 @@
+const modules = [
+ {
+ name: 'admin-hub',
+ entry: './src/admin-hub/module',
+ root: 'admin-hub-container',
+ generate: true
+ },
+ {
+ name: 'work-hub',
+ entry: './src/work-hub/module',
+ root: 'work-hub-container',
+ generate: true,
+ assets: [
+ { source: './src/work-hub/assets/hub-icon-dark.png', dest: 'assets/hub-icon-dark.png' },
+ { source: './src/work-hub/assets/hub-icon-light.png', dest: 'assets/hub-icon-light.png' },
+ { source: './hub-group-icon.png', dest: 'assets/hub-group-icon.png' }
+ ]
+ },
+ {
+ name: 'criteria-panel',
+ entry: './src/criteria-panel/module',
+ root: 'criteria-panel-container',
+ generate: true
+ },
+ {
+ name: 'wi-control',
+ entry: './src/wi-control/module',
+ root: 'wi-control-container',
+ generate: true
+ },
+ {
+ name: 'confirmation-dialog',
+ entry: './src/confirmation-dialog/module',
+ root: 'confirmation-dialog-container',
+ generate: true
+ },
+ {
+ name: 'progress-control',
+ entry: './src/progress-control/module',
+ root: 'progress-control-container',
+ generate: true
+ }
+];
+
+const entries = modules.reduce(
+ (obj, item) => ({
+ ...obj,
+ [item.name]: item.entry
+ }),
+ {}
+);
+
+module.exports = {
+ modules,
+ entries
+};
diff --git a/build-scripts/webpack-script-tags-plugin.js b/build-scripts/webpack-script-tags-plugin.js
new file mode 100644
index 0000000..853df6b
--- /dev/null
+++ b/build-scripts/webpack-script-tags-plugin.js
@@ -0,0 +1,17 @@
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+class ScriptTags {
+ apply(compiler) {
+ compiler.hooks.compilation.tap('ScriptTags', compilation => {
+ HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('ScriptTags', (data, cb) => {
+ const newData = { ...data };
+
+ for (const script of newData.assetTags.scripts) {
+ script.attributes.charset = 'UTF-8';
+ }
+ cb(null, newData);
+ });
+ });
+ }
+}
+module.exports = ScriptTags;
diff --git a/build-scripts/webpack.common.js b/build-scripts/webpack.common.js
new file mode 100644
index 0000000..19cd4d1
--- /dev/null
+++ b/build-scripts/webpack.common.js
@@ -0,0 +1,107 @@
+const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const ScriptTags = require('./webpack-script-tags-plugin');
+const { entries, modules } = require('./entry-points');
+const CopyPlugin = require('copy-webpack-plugin');
+const { EnvironmentPlugin } = require('webpack');
+const { getModuleVersions, getExtensionVersion } = require('./webpack.utils');
+
+const vendorGroups = modules.reduce(
+ (obj, item) => ({
+ ...obj,
+ [`${item.name}-vendor`]: {
+ test: /[\\/]node_modules[\\/]/,
+ name: `${item.name}.vendor`,
+ enforce: true,
+ chunks: chunk => {
+ return chunk.name === item.name;
+ }
+ }
+ }),
+ {}
+);
+
+console.log(vendorGroups);
+
+module.exports = {
+ devtool: 'inline-source-map',
+ mode: 'development',
+ entry: entries,
+ resolve: {
+ extensions: ['.ts', '.tsx', '.js'],
+ alias: {
+ 'azure-devops-extension-sdk': path.resolve('node_modules/azure-devops-extension-sdk'),
+ react: path.resolve('node_modules/react'),
+ 'react-dom': path.resolve('node_modules/react-dom')
+ }
+ },
+ // stats: 'errors-only',
+ optimization: {
+ runtimeChunk: {
+ name: entrypoint => `${entrypoint.name}.runtime`
+ },
+ splitChunks: {
+ cacheGroups: vendorGroups
+ }
+ },
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ loader: 'ts-loader'
+ },
+ {
+ test: /\.scss$/,
+ use: [
+ 'azure-devops-ui/buildScripts/css-variables-loader',
+ 'style-loader',
+ 'css-loader',
+ 'sass-loader'
+ ]
+ },
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader']
+ },
+ {
+ test: /\.woff$/,
+ type: 'asset/resource',
+ generator: {
+ filename: '[name][ext]'
+ }
+ }
+ ]
+ },
+ plugins: [
+ new ScriptTags(),
+ new EnvironmentPlugin({
+ ...getModuleVersions(modules),
+ ...getExtensionVersion()
+ })
+ ]
+ .concat(
+ modules
+ .filter(x => x.generate)
+ .map(entry => {
+ return new HtmlWebpackPlugin({
+ meta: {
+ charset: 'UTF-8'
+ },
+ filename: entry.name + '.html',
+ inject: false,
+ templateContent: ({ htmlWebpackPlugin }) =>
+ `${htmlWebpackPlugin.tags.headTags}${htmlWebpackPlugin.tags.bodyTags}`,
+ chunks: [entry.name]
+ });
+ })
+ )
+ .concat(
+ modules
+ .filter(x => x.assets !== undefined)
+ .map(entry => {
+ return new CopyPlugin({
+ patterns: entry.assets.map(asset => ({ from: asset.source, to: asset.dest }))
+ });
+ })
+ )
+};
diff --git a/build-scripts/webpack.config.dev.js b/build-scripts/webpack.config.dev.js
new file mode 100644
index 0000000..a6b7cf4
--- /dev/null
+++ b/build-scripts/webpack.config.dev.js
@@ -0,0 +1,41 @@
+const path = require('path');
+const { merge } = require('webpack-merge');
+const common = require('./webpack.common.js');
+const { getOutputName } = require('./webpack.utils');
+
+module.exports = merge(common, {
+ devServer: {
+ watchFiles: {
+ paths: ['src/**']
+ },
+ devMiddleware: {
+ writeToDisk: false
+ // stats: 'errors-only'
+ },
+ client: {
+ overlay: {
+ warnings: false,
+ errors: true
+ }
+ },
+ server: {
+ type: "https"
+ },
+ port: 3000,
+ hot: true,
+ static: [path.resolve(__dirname, '..', 'dist')],
+ historyApiFallback: {
+ disableDotRule: true,
+ rewrites: [{ from: /\/static\/.+/, to: '/' }]
+ }
+ },
+ output: {
+ publicPath: '/',
+ filename: pathData => {
+ return `static/${getOutputName(pathData.chunk.name)}.js`;
+ },
+ library: '[name]',
+ libraryTarget: 'umd',
+ clean: true
+ }
+});
diff --git a/build-scripts/webpack.config.prod.js b/build-scripts/webpack.config.prod.js
new file mode 100644
index 0000000..c38d413
--- /dev/null
+++ b/build-scripts/webpack.config.prod.js
@@ -0,0 +1,16 @@
+const { merge } = require('webpack-merge');
+const common = require('./webpack.common.js');
+const { getOutputName } = require('./webpack.utils');
+
+module.exports = merge(common, {
+ mode: 'production',
+ output: {
+ publicPath: '',
+ filename: pathData => {
+ return `static/${getOutputName(pathData.chunk.name)}.[chunkhash:8].js`;
+ },
+ library: '[name]',
+ libraryTarget: 'umd',
+ clean: true
+ }
+});
diff --git a/build-scripts/webpack.utils.js b/build-scripts/webpack.utils.js
new file mode 100644
index 0000000..8da4c1c
--- /dev/null
+++ b/build-scripts/webpack.utils.js
@@ -0,0 +1,26 @@
+const vssConfig = require('../vss-extension.prod.json');
+const id = [vssConfig.publisher.toLowerCase(), vssConfig.id.toLowerCase()];
+const fs = require('fs');
+
+module.exports = {
+ getOutputName(moduleName) {
+ return [...id, moduleName].join('.');
+ },
+ getModuleVersions(modules) {
+ return modules
+ .filter(x => x.generate)
+ .reduce((obj, item) => {
+ const moduleFile = JSON.parse(fs.readFileSync(`${item.entry}.json`).toString());
+ const version = `${moduleFile.version.Major}.${moduleFile.version.Minor}.${moduleFile.version.Patch}`;
+ return {
+ ...obj,
+ [`${item.name.replace(new RegExp('-', 'g'), '_').toUpperCase()}_VERSION`]: version
+ };
+ }, {});
+ },
+ getExtensionVersion() {
+ return {
+ EXTENSION_VERSION: process.env.TASK_EXTENSION_VERSION || vssConfig.version
+ };
+ }
+};
diff --git a/docs/CHANGELOG-DEV.md b/docs/CHANGELOG-DEV.md
deleted file mode 100644
index 96c4098..0000000
--- a/docs/CHANGELOG-DEV.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Changelog
-
-## 0.0.2 (2021-11-19)
-
-#### ➕ Added
-
-- Added panel
-
-## 0.0.1 (2021-11-16)
-
-#### ➕ Added
-
-- Added control
-
-
diff --git a/docs/CHANGELOG-PROD.md b/docs/CHANGELOG-PROD.md
deleted file mode 100644
index 99331df..0000000
--- a/docs/CHANGELOG-PROD.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Changelog
-
-## 0.0.1 (2021-11-16)
-
-#### ➕ Added
-
-- Added control
-
-
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
deleted file mode 100644
index 99331df..0000000
--- a/docs/CHANGELOG.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Changelog
-
-## 0.0.1 (2021-11-16)
-
-#### ➕ Added
-
-- Added control
-
-
diff --git a/docs/README-BASE.md b/docs/README-BASE.md
deleted file mode 100644
index 3139678..0000000
--- a/docs/README-BASE.md
+++ /dev/null
@@ -1 +0,0 @@
-# Adcanced Acceptance Criterias
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 3139678..0000000
--- a/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Adcanced Acceptance Criterias
diff --git a/extension-icon.png b/extension-icon.png
index ea15e2987c905c58b10af1cc1020c31826d5865d..fead4d87376192df0b85f446d3c672aa6653dc98 100644
GIT binary patch
literal 4219
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
diff --git a/hub-group-icon.png b/hub-group-icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..c0a41cb0f28dbab12a189223c49131d74acc86dc
GIT binary patch
literal 4917
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
literal 0
HcmV?d00001
diff --git a/marketplace/docs/images/.gitkeep b/marketplace/docs/images/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/marketplace/docs/images/panel-preview.png b/marketplace/docs/images/panel-preview.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a40c8485f881c85ecee2e2a8bbd17b029bcd5a1
GIT binary patch
literal 61595
zcmXtf1yoyI(>0U=#Y=H7#ogV#xEF`w4#h1%aR^o%g1bX;cXtWy?!jGu`n=ztwX(8q
z);VY9Oy=x8xpz;Pl7bWpB0eG%6cmc|cX1Ucs1IrHZ^}<_@87)QYuCSjd~_0(R{Qk+
z0(>$FeZR(Yme6!owKsEiGjueCGPkq0HDz!zb~H7$bF#2^K7;8Hgo64CB`q$Z=AL%4
z>IT5LAsM)s*NZ(>F{4r9G(Bs(Q&LhB4$h*7#WFciR95?pr6de1p{ykQN8n?8o7-Z}4
z2A@a+Ka1wcD97hDteA@&(g_LV6M(flSst5^{qGV`NNhXfh3Vdhgi29(d>z%5c2c;U
z&3Af<>f`3`{m~BbI5?!9GTi{2|4DiLkV14%E{yoT;FfgE)XHTRGzSCyI#n?+p9j}R~VZrfcuKOuk>|9c$#Bz&cVJPp8~;&;Jf-l?wkBldkI
z{OEx9)4TCcF)r23()_u^?7{`QFd$JL&m*@MqtVg5D=BPt63580Uip7kX%dGxqAZ&y
zpgcO3WA5DxBY#z89k=M+T(I-5#aM~ZtT+gfvh+j`ZCrw8{`2!&cwPc4aqR~Md3;PT
zEmP3Xlxf#Iu25b+4lq{p;SPg$h5c&;iJ7%$*>$)8nvTVI=oPWQuGQVFO(XZ{h^
zbSIy;TiLlxuukJ~3tMPxG%@9d1IPDJkw<-Vd<9=rjeB#02OTQ>jhaOZTvDD;fYCac
z(t7j6HXlS
zdt-5N+OxDO`9_v%>JsYeO2X=Dn9i~ic{zXhG*D%*>1^bq5xvleO`j@YbX$DD`iV}1
za>RnFWi&46{E-T7dFP>deiJU`MaQOWUs%tCG|f&NqIG^_y`gNPqepvU1iF_k+#>Mo
z0pIZTxP&IR+146ZZ+2~;G{KLv#p>lBO1gvr0DiatXoRvivzKKM(
zN|1_Lu@bPH@27FKEMT_%Y!GUlrga+lqbjV%_OpajLBd!5)Q_8%sae1%6kRn0$vBCjvF*tfa35N1{yuz}|M=6qRrDEWsGamR
zd>Zk0O2(I1tfGa6TwxzyeVbKWMK`W5TNp}eSQ6^W>XRHO0Ye`<6aHKUzB<9`g;PnL
z@?%mfKK_=-8LN=_1mow@|vS^j)(lsJ*}W;(ma1wAeVz>#5OivUb{V=E^ceeI6S8=Mk&6Sc+P3>P#Gi
zotAG!+M*@6l~Gc?%Z5`2H0nYm0Y6r@y|+2Oy4=9+@r#M8Qm^NCRLGEc?-)VgDk6n_
z)%4Do!SDMA3(^I7~k*~xdMNYO4Ca_1;=3;
z$<@GdFsDS2lap&cnbT&`76F5Yb|eov-hNr^yLNYXUtFIHE2}$WVoFdP?a4=l*ohUd
z{?>hcCGQ>3v63pMQ&q!q+fV+Sh`^;$7VxWJUhd_
z?AL=&?Lz2ZbS2VvQO3!V*Nl6Zaean70Z!>(y;H8C6_+F@@6AogUsMXsGg<%KjkW)~
zxDbn5Z$+=cOv2IRj)GLMt3ATV7Te8Dqsiq8uJHEcDErX}m9Df{L&
zL_$~hgH%9+a+L^1Yn%6^t^6f5H7K~ka%U(#eNX!GJ(irFs*Fi=wicQcPBE7|f-KQO|h@C3`()Jd{gF3dQmH{Nqs=pj+i((-~ci~g+=
z=+3@{@rB#vk-tzO(_HG@2cNTO=!T%-@7SKDtvWnC#w>x_tSLjGe066^``_a1Aqi%xtY)k`3NfduT48KuZNt*nl|Lnk$^{>;nI9
zR$=F14Gwb=oU`6QSqg(59Y+YFbf*pE?hvTDQ5#LGSgm9vl6c7AET1HMkMPe9zl2@j
zTJ^qgjf>B!Nx-