diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml new file mode 100644 index 00000000..bee22d90 --- /dev/null +++ b/.github/workflows/continuous.yml @@ -0,0 +1,65 @@ +name: continuous + +on: [push] + +jobs: + tests: + name: tests + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: Tests + run: ./build.ps1 Tests -Configuration Debug + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v3 + with: + name: Test Results (${{ runner.os }}) + path: output/**/*_testresults.xml + upload-docs: + needs: tests + name: upload-docs + runs-on: windows-latest + env: + GitHubAuthenticationToken: ${{ secrets.GITHUB_TOKEN }} + DocuApiKey: ${{ secrets.DOCUAPIKEY }} + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: UploadDocumentation+PublishGitHubRelease + run: ./build.ps1 UploadDocumentation+PublishGitHubRelease + upload-electron-app: + needs: upload-docs + name: upload-electron-app + runs-on: windows-latest + env: + GitHubAuthenticationToken: ${{ secrets.GITHUB_TOKEN }} + DocuApiKey: ${{ secrets.DOCUAPIKEY }} + CodeSigningCertificateKeyVaultBaseUrl: ${{ secrets.CODESIGNINGKEYVAULTBASEURL }} + KeyVaultClientId: ${{ secrets.CODESIGNINGKEYVAULTCLIENTID }} + KeyVaultClientSecret: ${{ secrets.CODESIGNINGKEYVAULTCLIENTSECRET }} + CodeSigningKeyVaultTenantId: ${{ secrets.CODESIGNINGKEYVAULTTENANTID }} + CodeSigningCertificateName: ${{ secrets.CODESIGNINGKEYVAULTCERTIFICATENAME }} + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: UploadElectronApp + run: ./build.ps1 UploadElectronApp --skip UploadDocumentation BuildDocumentation BuildDocFxMetadata + upload-revit-plugin: + needs: upload-docs + name: upload-revit-plugin + runs-on: windows-latest + env: + GitHubAuthenticationToken: ${{ secrets.GITHUB_TOKEN }} + DocuApiKey: ${{ secrets.DOCUAPIKEY }} + CodeSigningCertificateKeyVaultBaseUrl: ${{ secrets.CODESIGNINGKEYVAULTBASEURL }} + KeyVaultClientId: ${{ secrets.CODESIGNINGKEYVAULTCLIENTID }} + KeyVaultClientSecret: ${{ secrets.CODESIGNINGKEYVAULTCLIENTSECRET }} + CodeSigningKeyVaultTenantId: ${{ secrets.CODESIGNINGKEYVAULTTENANTID }} + CodeSigningCertificateName: ${{ secrets.CODESIGNINGKEYVAULTCERTIFICATENAME }} + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: UploadRevitPlugin + run: ./build.ps1 UploadRevitPlugin diff --git a/.gitignore b/.gitignore index 57a1574c..ec6be201 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ [Rr]eleases/ x64/ x86/ -build/ bld/ [Bb]in/ [Oo]bj/ @@ -194,3 +193,11 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt + +output/ + +nuke2/ + +src/IPA.Bcfier.App/wwwroot/dist/ + +src/IPA.Bcfier.Revit/Resources/Browser/ diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json new file mode 100644 index 00000000..66ec3a77 --- /dev/null +++ b/.nuke/build.schema.json @@ -0,0 +1,170 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/build", + "title": "Build Schema", + "definitions": { + "build": { + "type": "object", + "properties": { + "CodeSigningCertificateKeyVaultBaseUrl": { + "type": "string" + }, + "CodeSigningCertificateName": { + "type": "string" + }, + "CodeSigningKeyVaultTenantId": { + "type": "string" + }, + "Configuration": { + "type": "string", + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", + "enum": [ + "Debug", + "Release" + ] + }, + "Continue": { + "type": "boolean", + "description": "Indicates to continue a previously failed build attempt" + }, + "DocuApiKey": { + "type": "string" + }, + "DocuBaseUrl": { + "type": "string" + }, + "ExecutablesToSignFolder": { + "type": "string" + }, + "GitHubAuthenticationToken": { + "type": "string" + }, + "Help": { + "type": "boolean", + "description": "Shows the help text for this build assembly" + }, + "Host": { + "type": "string", + "description": "Host for execution. Default is 'automatic'", + "enum": [ + "AppVeyor", + "AzurePipelines", + "Bamboo", + "Bitbucket", + "Bitrise", + "GitHubActions", + "GitLab", + "Jenkins", + "Rider", + "SpaceAutomation", + "TeamCity", + "Terminal", + "TravisCI", + "VisualStudio", + "VSCode" + ] + }, + "KeyVaultClientId": { + "type": "string" + }, + "KeyVaultClientSecret": { + "type": "string" + }, + "MigrationName": { + "type": "string" + }, + "NoLogo": { + "type": "boolean", + "description": "Disables displaying the NUKE logo" + }, + "Partition": { + "type": "string", + "description": "Partition to use on CI" + }, + "Plan": { + "type": "boolean", + "description": "Shows the execution plan (HTML)" + }, + "Profile": { + "type": "array", + "description": "Defines the profiles to load", + "items": { + "type": "string" + } + }, + "Root": { + "type": "string", + "description": "Root directory during build execution" + }, + "Skip": { + "type": "array", + "description": "List of targets to be skipped. Empty list skips all dependencies", + "items": { + "type": "string", + "enum": [ + "BuildDocFxMetadata", + "BuildDocumentation", + "BuildElectronApp", + "BuildFrontend", + "BuildFrontendSwaggerClient", + "BuildRevitPlugin", + "Clean", + "Compile", + "CreateMigration", + "FrontEndRestore", + "GenerateFrontendVersion", + "PublishGitHubRelease", + "Restore", + "SignExecutables", + "Tests", + "UploadDocumentation", + "UploadElectronApp", + "UploadRevitPlugin" + ] + } + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + }, + "Target": { + "type": "array", + "description": "List of targets to be invoked. Default is '{default_target}'", + "items": { + "type": "string", + "enum": [ + "BuildDocFxMetadata", + "BuildDocumentation", + "BuildElectronApp", + "BuildFrontend", + "BuildFrontendSwaggerClient", + "BuildRevitPlugin", + "Clean", + "Compile", + "CreateMigration", + "FrontEndRestore", + "GenerateFrontendVersion", + "PublishGitHubRelease", + "Restore", + "SignExecutables", + "Tests", + "UploadDocumentation", + "UploadElectronApp", + "UploadRevitPlugin" + ] + } + }, + "Verbosity": { + "type": "string", + "description": "Logging verbosity during build execution. Default is 'Normal'", + "enum": [ + "Minimal", + "Normal", + "Quiet", + "Verbose" + ] + } + } + } + } +} diff --git a/.nuke/parameters.json b/.nuke/parameters.json new file mode 100644 index 00000000..fdd4aaca --- /dev/null +++ b/.nuke/parameters.json @@ -0,0 +1,4 @@ +{ + "$schema": "./build.schema.json", + "Solution": "IPA.BCFier.sln" +} diff --git a/AssemblyVersionInfo.cs b/AssemblyVersionInfo.cs deleted file mode 100644 index f35062c0..00000000 --- a/AssemblyVersionInfo.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Reflection; -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.2")] -[assembly: AssemblyFileVersion("2.2.2")] diff --git a/BCFier.exe b/BCFier.exe deleted file mode 100755 index 5bb277fb..00000000 Binary files a/BCFier.exe and /dev/null differ diff --git a/BCFier.sln b/BCFier.sln deleted file mode 100644 index a19fcbef..00000000 --- a/BCFier.sln +++ /dev/null @@ -1,202 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bcfier", "Bcfier\Bcfier.csproj", "{503CE2C1-09D7-4F15-BB42-86196EE01ED4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bcfier.Revit", "Bcfier.Revit\Bcfier.Revit.csproj", "{2D132990-5674-42DF-93BF-55BA8FDC6A23}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bcfier.Win", "Bcfier.Win\Bcfier.Win.csproj", "{3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bcfier.Navisworks", "Bcfier.Navisworks\Bcfier.Navisworks.csproj", "{CAF05B60-6A81-489D-B966-7B94F0D69AC7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bcfier.XbimXplorer", "Bcfier.XbimXplorer\Bcfier.XbimXplorer.csproj", "{4CD7CA76-A40E-4DF4-831D-36B64818CC69}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug-2015|Any CPU = Debug-2015|Any CPU - Debug-2016|Any CPU = Debug-2016|Any CPU - Debug-2017|Any CPU = Debug-2017|Any CPU - Debug-2018|Any CPU = Debug-2018|Any CPU - Debug-2019|Any CPU = Debug-2019|Any CPU - Debug-2020|Any CPU = Debug-2020|Any CPU - Debug-2021|Any CPU = Debug-2021|Any CPU - Debug-2022|Any CPU = Debug-2022|Any CPU - Release|Any CPU = Release|Any CPU - Release-2015|Any CPU = Release-2015|Any CPU - Release-2016|Any CPU = Release-2016|Any CPU - Release-2017|Any CPU = Release-2017|Any CPU - Release-2018|Any CPU = Release-2018|Any CPU - Release-2019|Any CPU = Release-2019|Any CPU - Release-2020|Any CPU = Release-2020|Any CPU - Release-2021|Any CPU = Release-2021|Any CPU - Release-2022|Any CPU = Release-2022|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2015|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2015|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2016|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2016|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2017|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2017|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2018|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2018|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2019|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2019|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2020|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2020|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2021|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2021|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2022|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Debug-2022|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2015|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2015|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2016|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2016|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2017|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2017|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2018|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2018|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2019|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2019|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2020|Any CPU.ActiveCfg = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2020|Any CPU.Build.0 = Debug|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2021|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2021|Any CPU.Build.0 = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2022|Any CPU.ActiveCfg = Release|Any CPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4}.Release-2022|Any CPU.Build.0 = Release|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2015|Any CPU.ActiveCfg = Debug-2015|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2015|Any CPU.Build.0 = Debug-2015|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2016|Any CPU.ActiveCfg = Debug-2016|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2016|Any CPU.Build.0 = Debug-2016|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2017|Any CPU.ActiveCfg = Debug-2017|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2017|Any CPU.Build.0 = Debug-2017|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2018|Any CPU.ActiveCfg = Debug-2018|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2018|Any CPU.Build.0 = Debug-2018|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2019|Any CPU.ActiveCfg = Debug-2019|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2019|Any CPU.Build.0 = Debug-2019|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2020|Any CPU.ActiveCfg = Debug-2020|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2020|Any CPU.Build.0 = Debug-2020|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2021|Any CPU.ActiveCfg = Debug-2021|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2021|Any CPU.Build.0 = Debug-2021|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2022|Any CPU.ActiveCfg = Debug-2022|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Debug-2022|Any CPU.Build.0 = Debug-2022|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release|Any CPU.Build.0 = Release|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2015|Any CPU.ActiveCfg = Release-2015|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2015|Any CPU.Build.0 = Release-2015|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2016|Any CPU.ActiveCfg = Release-2016|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2016|Any CPU.Build.0 = Release-2016|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2017|Any CPU.ActiveCfg = Release-2017|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2017|Any CPU.Build.0 = Release-2017|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2018|Any CPU.ActiveCfg = Release-2018|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2018|Any CPU.Build.0 = Release-2018|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2019|Any CPU.ActiveCfg = Release-2019|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2019|Any CPU.Build.0 = Release-2019|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2020|Any CPU.ActiveCfg = Release-2020|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2020|Any CPU.Build.0 = Release-2020|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2021|Any CPU.ActiveCfg = Release-2021|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2021|Any CPU.Build.0 = Release-2021|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2022|Any CPU.ActiveCfg = Release-2022|Any CPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23}.Release-2022|Any CPU.Build.0 = Release-2022|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2015|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2015|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2016|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2016|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2017|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2017|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2018|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2018|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2019|Any CPU.ActiveCfg = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2019|Any CPU.Build.0 = Debug|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2020|Any CPU.ActiveCfg = Debug-2020|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2021|Any CPU.ActiveCfg = Debug-2021|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Debug-2022|Any CPU.ActiveCfg = Debug-2021|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2015|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2015|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2016|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2016|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2017|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2017|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2018|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2018|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2019|Any CPU.ActiveCfg = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2019|Any CPU.Build.0 = Release|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2020|Any CPU.ActiveCfg = Release-2020|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2021|Any CPU.ActiveCfg = Release-2021|Any CPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B}.Release-2022|Any CPU.ActiveCfg = Release-2021|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2015|Any CPU.ActiveCfg = Debug-2015|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2015|Any CPU.Build.0 = Debug-2015|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2016|Any CPU.ActiveCfg = Debug-2016|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2016|Any CPU.Build.0 = Debug-2016|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2017|Any CPU.ActiveCfg = Debug-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2017|Any CPU.Build.0 = Debug-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2018|Any CPU.ActiveCfg = Debug-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2019|Any CPU.ActiveCfg = Debug-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2020|Any CPU.ActiveCfg = Debug-2020|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2021|Any CPU.ActiveCfg = Debug-2021|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Debug-2022|Any CPU.ActiveCfg = Debug-2021|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release|Any CPU.Build.0 = Release|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2015|Any CPU.ActiveCfg = Release-2015|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2015|Any CPU.Build.0 = Release-2015|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2016|Any CPU.ActiveCfg = Release-2016|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2016|Any CPU.Build.0 = Release-2016|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2017|Any CPU.ActiveCfg = Release-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2017|Any CPU.Build.0 = Release-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2018|Any CPU.ActiveCfg = Release-2017|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2019|Any CPU.ActiveCfg = Release-2019|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2020|Any CPU.ActiveCfg = Release-2020|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2021|Any CPU.ActiveCfg = Release-2021|Any CPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7}.Release-2022|Any CPU.ActiveCfg = Release-2021|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2015|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2015|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2016|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2016|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2017|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2017|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2018|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2018|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2019|Any CPU.ActiveCfg = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2019|Any CPU.Build.0 = Debug|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2020|Any CPU.ActiveCfg = Debug-2020|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2021|Any CPU.ActiveCfg = Debug-2021|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Debug-2022|Any CPU.ActiveCfg = Debug-2021|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2015|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2015|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2016|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2016|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2017|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2017|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2018|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2018|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2019|Any CPU.ActiveCfg = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2019|Any CPU.Build.0 = Release|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2020|Any CPU.ActiveCfg = Release-2020|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2021|Any CPU.ActiveCfg = Release-2021|Any CPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69}.Release-2022|Any CPU.ActiveCfg = Release-2021|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {440C743A-A1DD-46EA-A56F-5A92471914C6} - EndGlobalSection -EndGlobal diff --git a/Bcfier.Navisworks/Bcfier.Navisworks.csproj b/Bcfier.Navisworks/Bcfier.Navisworks.csproj deleted file mode 100644 index 118f193f..00000000 --- a/Bcfier.Navisworks/Bcfier.Navisworks.csproj +++ /dev/null @@ -1,406 +0,0 @@ - - - - - Debug - AnyCPU - {CAF05B60-6A81-489D-B966-7B94F0D69AC7} - Library - Properties - Bcfier.Navisworks - Bcfier.Navisworks - v4.5 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - true - bin\Debug-2015\ - TRACE;DEBUG;Version2015 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2015 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Navisworks Manage 2015\Roamer.exe - v4.5 - - - bin\Release-2015\ - TRACE;RELEASE;Version2015 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2015 - $(AssemblyName) - 0 - - None - - false - v4.5 - - - - true - bin\Debug-2016\ - TRACE;DEBUG;Version2016 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2016 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Navisworks Manage 2016\Roamer.exe - v4.5 - - - bin\Release-2016\ - TRACE;RELEASE;Version2016 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2016 - $(AssemblyName) - 0 - - None - - false - v4.5 - - - - true - bin\Debug-2017\ - TRACE;DEBUG;Version2017 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2017 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Navisworks Manage 2017\Roamer.exe - v4.6 - - - bin\Release-2017\ - TRACE;RELEASE;Version2017 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2017 - $(AssemblyName) - 0 - - None - - false - v4.6 - - - - - - true - bin\Debug-2019\ - TRACE;DEBUG;Version2017 - full - x64 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2019\ - TRACE;RELEASE;Version2017 - true - 0 - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2021\ - TRACE;DEBUG;Version2017 - full - x64 - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2021\ - TRACE;RELEASE;Version2017 - true - 0 - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release2020\ - TRACE;RELEASE;Version2017 - true - 0 - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2020\ - TRACE;DEBUG;Version2017 - full - x64 - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - - - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.Interop.ComApi.dll - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.Interop.ComApi.dll - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.Interop.ComApi.dll - - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2015\Autodesk.Navisworks.Interop.ComApi.dll - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2016\Autodesk.Navisworks.Interop.ComApi.dll - - - - False - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.Api.dll - False - - - False - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.ComApi.dll - False - - - False - True - C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk.Navisworks.Interop.ComApi.dll - - - - - - - - - - - - - 4.0 - - - - - - - - - - - - - NavisWindow.xaml - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - AddViewNavis.xaml - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - Designer - MSBuild:Compile - Always - - - - - Always - - - Always - - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - {503ce2c1-09d7-4f15-bb42-86196ee01ed4} - Bcfier - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier.Navisworks/Data/NavisUtils.cs b/Bcfier.Navisworks/Data/NavisUtils.cs deleted file mode 100644 index c767b369..00000000 --- a/Bcfier.Navisworks/Data/NavisUtils.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Autodesk.Navisworks.Api; -using Bcfier.Bcf.Bcf2; -using Point = Bcfier.Bcf.Bcf2.Point; -using Direction = Bcfier.Bcf.Bcf2.Direction; - -namespace Bcfier.Navisworks.Data -{ - public static class NavisUtils - { - private static double _Units; - - public static Point3D GetNavisXYZ(Point d) - { - return new Point3D(d.X.ToInternal(), d.Y.ToInternal(), d.Z.ToInternal()); - } - public static Vector3D GetNavisVector(Direction d) - { - return new Point3D(d.X.ToInternal(), d.Y.ToInternal(), d.Z.ToInternal()).ToVector3D().Normalize(); - } - - /// - /// Converts meters units to feet - /// - /// Value in feet to be converted to feet - /// - public static double ToInternal(this double meters) - { - return meters * _Units; - } - - public static double FromInternal(this double intUnits) - { - return intUnits / _Units; - } - - public static void GetGunits(Document doc) - { - string units = doc.Units.ToString(); - double factor = 1; - switch (units) - { - case "Centimeters": - factor = 100; - break; - case "Feet": - factor = 3.28084; - break; - case "Inches": - factor = 39.3701; - break; - case "Kilometers": - factor = 0.001; - break; - case "Meters": - factor = 1; - break; - case "Micrometers": - factor = 1000000; - break; - case "Miles": - factor = 0.000621371; - break; - case "Millimeters": - factor = 1000; - break; - case "Mils": - factor = 39370.0787; - break; - case "Yards": - factor = 1.09361; - break; - default: - //MessageBox.Show("Units " + units + " not recognized."); - factor = 1; - break; - } - _Units = factor; - } - } -} diff --git a/Bcfier.Navisworks/Data/NavisView.cs b/Bcfier.Navisworks/Data/NavisView.cs deleted file mode 100644 index 914a157c..00000000 --- a/Bcfier.Navisworks/Data/NavisView.cs +++ /dev/null @@ -1,267 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using Autodesk.Navisworks.Api; -using Bcfier.Bcf.Bcf2; -using Bcfier.Data.Utils; - -namespace Bcfier.Navisworks.Data -{ - public static class NavisView - { - public static void Open(Document doc, VisualizationInfo v) - { - try - { - - NavisUtils.GetGunits(doc); - Viewpoint viewpoint = new Viewpoint(); - - //orthogonal - if (v.OrthogonalCamera != null) - { - if (v.OrthogonalCamera.CameraViewPoint == null || v.OrthogonalCamera.CameraUpVector == null || - v.OrthogonalCamera.CameraDirection == null) - return; - - var zoom = v.OrthogonalCamera.ViewToWorldScale.ToInternal(); - var cameraDirection = NavisUtils.GetNavisVector(v.OrthogonalCamera.CameraDirection); - var cameraUpVector = NavisUtils.GetNavisVector(v.OrthogonalCamera.CameraUpVector); - var cameraViewPoint = NavisUtils.GetNavisXYZ(v.OrthogonalCamera.CameraViewPoint); - - viewpoint.Position = cameraViewPoint; - viewpoint.AlignUp(cameraUpVector); - viewpoint.AlignDirection(cameraDirection); - viewpoint.Projection = ViewpointProjection.Orthographic; - viewpoint.FocalDistance = 1; - - //TODO - //for better zooming from revit should use > zoom * 1.25 - //for better zooming from tekla should use > zoom / 1.25 - //still not sure why - Point3D xyzTL = cameraViewPoint.Add(cameraUpVector.Multiply(zoom)); - var dist = xyzTL.DistanceTo(cameraViewPoint); - viewpoint.SetExtentsAtFocalDistance(1, dist); - } - //perspective - else if (v.PerspectiveCamera != null) - { - if (v.PerspectiveCamera.CameraViewPoint == null || v.PerspectiveCamera.CameraUpVector == null || - v.PerspectiveCamera.CameraDirection == null) - return; - - var zoom = v.PerspectiveCamera.FieldOfView; - var cameraDirection = NavisUtils.GetNavisVector(v.PerspectiveCamera.CameraDirection); - var cameraUpVector = NavisUtils.GetNavisVector(v.PerspectiveCamera.CameraUpVector); - var cameraViewPoint = NavisUtils.GetNavisXYZ(v.PerspectiveCamera.CameraViewPoint); - - viewpoint.Position = cameraViewPoint; - viewpoint.AlignUp(cameraUpVector); - viewpoint.AlignDirection(cameraDirection); - viewpoint.Projection = ViewpointProjection.Perspective; - viewpoint.FocalDistance = zoom; - } - - doc.CurrentViewpoint.CopyFrom(viewpoint); - - - //show/hide elements - //todo: needs improvement - //todo: add settings - if (v.Components != null && v.Components.Any()) - { - List attachedElems = new List(); - List elems = doc.Models.First.RootItem.DescendantsAndSelf.ToList(); - - - foreach (var item in elems.Where(o => o.InstanceGuid != Guid.Empty)) - { - string ifcguid = IfcGuid.ToIfcGuid(item.InstanceGuid).ToString(); - if (v.Components.Any(o => o.IfcGuid == ifcguid)) - attachedElems.Add(item); - - } - if (attachedElems.Any()) //avoid to hide everything if no elements matches - { - if (UserSettings.Get("selattachedelems") == "0") - { - List elemsVisible = new List(); - foreach (var item in attachedElems) - { - elemsVisible.AddRange(item.AncestorsAndSelf); - } - foreach (var item in elemsVisible) - elems.Remove(item); - - doc.Models.ResetAllHidden(); - doc.Models.SetHidden(elems, true); - } - else - { - doc.CurrentSelection.Clear(); - doc.CurrentSelection.AddRange(attachedElems); - } - } - } - } - - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error opening view"); - } - } - - // - //Generate a VisualizationInfo of the current view - // - // - public static VisualizationInfo GenerateViewpoint(Document doc, Viewpoint viewpoint) - { - try - { - NavisUtils.GetGunits(doc); - var v = new VisualizationInfo(); - - Vector3D vi = GetViewDirection(viewpoint); - Vector3D up = GetViewUp(viewpoint); - Point3D c = new Point3D(viewpoint.Position.X, viewpoint.Position.Y, viewpoint.Position.Z); - double zoomValue = 1; - - //prepare view - viewpoint = viewpoint.CreateCopy(); - if (!viewpoint.HasFocalDistance) - viewpoint.FocalDistance = 1; - - // it is a orthogonal view - if (viewpoint.Projection == ViewpointProjection.Orthographic) - { - //TODO: needs checking!!! - double dist = viewpoint.VerticalExtentAtFocalDistance / 2; - zoomValue = 3.125 * dist / (up.Length * 1.25); - - - v.OrthogonalCamera = new OrthogonalCamera - { - CameraViewPoint = - { - X = c.X.FromInternal(), - Y = c.Y.FromInternal(), - Z = c.Z.FromInternal() - }, - CameraUpVector = - { - X = up.X.FromInternal(), - Y = up.Y.FromInternal(), - Z = up.Z.FromInternal() - }, - CameraDirection = - { - X = vi.X.FromInternal(), - Y = vi.Y.FromInternal(), - Z = vi.Z.FromInternal() - }, - ViewToWorldScale = zoomValue.FromInternal() - }; - } - else - { - zoomValue = viewpoint.FocalDistance; - - v.PerspectiveCamera = new PerspectiveCamera - { - CameraViewPoint = - { - X = c.X.FromInternal(), - Y = c.Y.FromInternal(), - Z = c.Z.FromInternal() - }, - CameraUpVector = - { - X = up.X.FromInternal(), - Y = up.Y.FromInternal(), - Z = up.Z.FromInternal() - }, - CameraDirection = - { - X = vi.X.FromInternal(), - Y = vi.Y.FromInternal(), - Z = vi.Z.FromInternal() - }, - FieldOfView = zoomValue - }; - - } - //COMPONENTS PART - - //if (elemCheck == 0)//visible (0) - // _elementList = _oDoc.Models.First.RootItem.DescendantsAndSelf.Where(o => o.InstanceGuid != Guid.Empty && ChechHidden(o.AncestorsAndSelf) && o.FindFirstGeometry() != null && !o.FindFirstGeometry().Item.IsHidden).ToList(); - - //if (null != _elementList && _elementList.Any() && elemCheck != 2)//not if none (2) - //{ - // v.Components = new Data.Component[_elementList.Count]; - // string appname = Autodesk.Navisworks.Api.Application.Title; - // for (var i = 0; i < _elementList.Count; i++) - // { - // string ifcguid = IfcGuid.ToIfcGuid(_elementList.ElementAt(i).InstanceGuid).ToString(); - // v.Components[i] = new Case.IssueTracker.Data.Component(appname, "", ifcguid); - - // } - //} - return v; - } - - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error generating viewpoint"); - } - return null; - - } - - private static Vector3D GetViewDirection(Viewpoint v) - { - - Rotation3D oRot = v.Rotation; - // calculate view direction - Rotation3D oNegtiveZ = new Rotation3D(0, 0, -1, 0); - Rotation3D otempRot = MultiplyRotation3D(oNegtiveZ, oRot.Invert()); - Rotation3D oViewDirRot = MultiplyRotation3D(oRot, otempRot); - // get view direction - Vector3D oViewDir = new Vector3D(oViewDirRot.A, oViewDirRot.B, oViewDirRot.C); - - return oViewDir.Normalize(); - } - private static Vector3D GetViewUp(Viewpoint v) - { - - Rotation3D oRot = v.Rotation; - // calculate view direction - Rotation3D oNegtiveZ = new Rotation3D(0, 1, 0, 0); - Rotation3D otempRot = MultiplyRotation3D(oNegtiveZ, oRot.Invert()); - Rotation3D oViewDirRot = MultiplyRotation3D(oRot, otempRot); - // get view direction - Vector3D oViewDir = new Vector3D(oViewDirRot.A, oViewDirRot.B, oViewDirRot.C); - - return oViewDir.Normalize(); - } - //multiply two Rotation3D - private static Rotation3D MultiplyRotation3D(Rotation3D r2,Rotation3D r1) - { - Rotation3D rot =new Rotation3D( - r2.D * r1.A + r2.A * r1.D + - r2.B * r1.C - r2.C * r1.B, - r2.D * r1.B + r2.B * r1.D + - r2.C * r1.A - r2.A * r1.C, - r2.D * r1.C + r2.C * r1.D + - r2.A * r1.B - r2.B * r1.A, - r2.D * r1.D - r2.A * r1.A - - r2.B * r1.B - r2.C * r1.C); - rot.Normalize(); - return rot; - } - - } -} diff --git a/Bcfier.Navisworks/Entry/AppMain.cs b/Bcfier.Navisworks/Entry/AppMain.cs deleted file mode 100644 index 6784a305..00000000 --- a/Bcfier.Navisworks/Entry/AppMain.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Windows.Forms; -using System.Windows.Forms.Integration; -using Autodesk.Navisworks.Api.Plugins; - -namespace Bcfier.Navisworks.Entry -{ - [Plugin("Bcfier.AppMain", "Bcfier", DisplayName = "BCFier", ToolTip = "Bcfier")] - [DockPanePlugin(800, 500, FixedSize = false)] - class AppMain : DockPanePlugin - { - NavisWindow ns; - - public override Control CreateControlPane() - { - //create an ElementHost - ElementHost eh = new ElementHost(); - - //assign the control - //eh.Anchor = AnchorStyles.Top; - eh.Dock = DockStyle.Top; - eh.Anchor = AnchorStyles.Top; - ns = new NavisWindow(); - eh.Child = ns; - eh.HandleCreated += eh_HandleCreated; - eh.CreateControl(); - - //return the ElementHost - return eh; - } - - void eh_HandleCreated(object sender, EventArgs e) - { - ElementHost eh = sender as ElementHost; - eh.Dock = DockStyle.Top; - eh.Anchor = AnchorStyles.Top; - - } - - public override void DestroyControlPane(Control pane) - { - //TODO: uncommet - //ns.mainPan.onClosing(null); - pane.Dispose(); - - } - } -} \ No newline at end of file diff --git a/Bcfier.Navisworks/Entry/CmdMain.cs b/Bcfier.Navisworks/Entry/CmdMain.cs deleted file mode 100644 index fc73d0ff..00000000 --- a/Bcfier.Navisworks/Entry/CmdMain.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using System.Windows.Forms; -using Autodesk.Navisworks.Api.Plugins; - -namespace Bcfier.Navisworks.Entry -{ - - [Plugin("Bcfier.CmdMain", "Bcfier", DisplayName = "BCFier")] - [RibbonLayout("RibbonDefinition.xaml")] - [RibbonTab("bcfierTab")] - [Command("bcfierBtn", DisplayName = "BCFier", Icon = "BCFierIcon16x16.png", LargeIcon = "BCFierIcon32x32.png", ToolTip = "BCFier", ExtendedToolTip = "BCFier")] - public class CmdMain : CommandHandlerPlugin - { -#if Version2017 - - public const string NavisVersion = "2017"; - -#elif Version2015 - - public const string NavisVersion = "2015"; - -#elif Version2016 - - public const string NavisVersion = "2016"; - -#endif - /// - /// Constructor, just initialises variables. - /// - public CmdMain() - { - - } - - public override int ExecuteCommand(string commandId, params string[] parameters) - { - switch (commandId) - { - case "bcfierBtn": - { - - LaunchPlugin(); - break; - } - - default: - { - MessageBox.Show("You have clicked on the command with ID = '" + commandId + "'"); - break; - } - } - - return 0; - } - - public override bool TryShowCommandHelp(String commandId) - { - MessageBox.Show("Showing Help for command with the Id " + commandId); - return true; - } - - /// - /// Launch - /// - public void LaunchPlugin() - { - - // Running Navis - if (Autodesk.Navisworks.Api.Application.IsAutomated) - { - throw new InvalidOperationException("Invalid when running using Automation"); - } - - // Version - if (!Autodesk.Navisworks.Api.Application.Version.RuntimeProductName.Contains(NavisVersion)) - { - MessageBox.Show("This Add - In was built and tested only for Navisworks Manage " + NavisVersion + ", proceed at your own risk", - "Untested Navisworks Version", - MessageBoxButtons.OK, - MessageBoxIcon.Warning); - } - - //Find the plugin - PluginRecord pr = Autodesk.Navisworks.Api.Application.Plugins.FindPlugin("Bcfier.AppMain.Bcfier"); - - if (pr != null && pr is DockPanePluginRecord && pr.IsEnabled) - { - //string bcfier = "Bcfier.Navisworks.dll"; - - //check if it needs loading - if (pr.LoadedPlugin == null) - { - pr.LoadPlugin(); - } - - DockPanePlugin dpp = pr.LoadedPlugin as DockPanePlugin; - if (dpp != null) - { - //switch the Visible flag - dpp.Visible = !dpp.Visible; - } - } - } - } -} - - - -// addin tab -// [Plugin("Bcfier.CmdMain", "Bcfier", DisplayName = "BCFier")] -// //[RibbonLayout("RibbonDefinition.xaml")] -// // [RibbonTab("bcfierTab")] -// [Command("bcfierBtn", DisplayName = "BCFier", Icon = "BCFierIcon16x16.png", LargeIcon = "BCFierIcon32x32.png", ToolTip = "BCFier", ExtendedToolTip = "BCFier")] -// public class BasicDockPaneAddin : AddInPlugin -// { -// public override int Execute(params string[] parameters) -// { -// // Find the plugin -// PluginRecord pr = Autodesk.Navisworks.Api.Application.Plugins.FindPlugin("Bcfier.AppMain.Bcfier"); - -// if (pr != null && pr is DockPanePluginRecord && pr.IsEnabled) -// { //check if it needs loading if (pr.LoadedPlugin == null) { pr.LoadPlugin(); } - -// DockPanePlugin dpp = pr.LoadedPlugin as DockPanePlugin; if (dpp != null) -// { // Switch the Visible flag -// dpp.Visible = !dpp.Visible; -// } -// } -// return 0; -// } -// } -//} \ No newline at end of file diff --git a/Bcfier.Navisworks/NavisWindow.xaml b/Bcfier.Navisworks/NavisWindow.xaml deleted file mode 100644 index 6cc89f31..00000000 --- a/Bcfier.Navisworks/NavisWindow.xaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/Bcfier.Navisworks/NavisWindow.xaml.cs b/Bcfier.Navisworks/NavisWindow.xaml.cs deleted file mode 100644 index 71ba1108..00000000 --- a/Bcfier.Navisworks/NavisWindow.xaml.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Linq; -using System.Collections.Generic; - -using System.IO; -using Bcfier.Data.Utils; -using Bcfier.Navisworks.Data; -using Bcfier.Bcf.Bcf2; -using Autodesk.Navisworks.Api; -using Bcfier.Navisworks.Windows; -using ComBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge; -using ComApi = Autodesk.Navisworks.Api.Interop.ComApi; - - -namespace Bcfier.Navisworks -{ - /// - /// Interaction logic for NavisWindow.xaml - /// - public partial class NavisWindow : UserControl - { - List _savedViewpoints = new List(); - - public NavisWindow() - { - InitializeComponent(); - - // set image export settings - // configure the option "export.image.format" to export png and image size - ComApi.InwOaPropertyVec options = ComBridge.State.GetIOPluginOptions("lcodpimage"); - foreach (ComApi.InwOaProperty opt in options.Properties()) - { - if (opt.name == "export.image.format") - opt.value = "lcodpexpng"; - if (opt.name == "export.image.width") - opt.value = 1600; - if (opt.name == "export.image.height") - opt.value = 900; - } - } - #region commands - /// - /// Raised when opening a view - /// - /// - /// - private void OnOpenView(object sender, ExecutedRoutedEventArgs e) - { - try - { - if (Bcfier.SelectedBcf() == null) - return; - var view = e.Parameter as ViewPoint; - if (view == null) - return; - - var v = view.VisInfo; - - //current document - var doc = Autodesk.Navisworks.Api.Application.ActiveDocument; - NavisView.Open(doc,v); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error opening a View!"); - } - } - /// - /// Same as in the windows app, but here we generate a VisInfo that is attached to the view - /// - /// - /// - private void OnAddView(object sender, ExecutedRoutedEventArgs e) - { - try - { - - if (Bcfier.SelectedBcf() == null) - return; - var issue = e.Parameter as Markup; - if (issue == null) - { - MessageBox.Show("No Issue selected", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return; - } - try - { - var doc = Autodesk.Navisworks.Api.Application.ActiveDocument; - var dialog = new AddViewNavis(issue, Bcfier.SelectedBcf().TempPath); - dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; - dialog.ShowDialog(); - if (dialog.DialogResult.HasValue && dialog.DialogResult.Value) - { - //generate and set the VisInfo - //issue.Viewpoints.Last().VisInfo = GenerateViewpoint(); - - //set filename here as it's not set when an issue is created - if (!string.IsNullOrEmpty(doc.FileName)) - issue.Header[0].Filename = doc.FileName; - else - issue.Header[0].Filename = "Unknown"; - - Bcfier.SelectedBcf().HasBeenSaved = false; - } - } - - catch (Exception ex) - { - MessageBox.Show(ex.ToString()); - } - - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error adding a View!"); - } - } - - private void OnAddIssues(object sender, ExecutedRoutedEventArgs e) - { - - } - - - - private void RecurseItems(SavedItem savedItem) - { - try - { - Autodesk.Navisworks.Api.GroupItem group = savedItem as Autodesk.Navisworks.Api.GroupItem; - //is a group - if (null != group) - { - foreach (SavedItem child in group.Children) - { - RecurseItems(child); - } - } - else - { - _savedViewpoints.Add((SavedViewpoint)savedItem); - } - } - catch - { - //do nothing - } - - } - - - #endregion - //stats - private void NavisWindow_OnLoaded(object sender, RoutedEventArgs e) - { - Task.Run(() => - { - StatHat.Post.EzCounter(@"hello@teocomi.com", "BCFierNavisStart", 1); - }); - } - } -} diff --git a/Bcfier.Navisworks/Properties/AssemblyInfo.cs b/Bcfier.Navisworks/Properties/AssemblyInfo.cs deleted file mode 100644 index c7b168a2..00000000 --- a/Bcfier.Navisworks/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bcfier.Navisworks")] -[assembly: AssemblyDescription("Bcfier.Navisworks")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("teocomi")] -[assembly: AssemblyProduct("Bcfier.Navisworks")] -[assembly: AssemblyCopyright("Copyright © teocomi 2017")] -[assembly: AssemblyTrademark("teocomi")] -[assembly: AssemblyCulture("")] - - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.1.0")] -[assembly: AssemblyFileVersion("2.1.0")] -[assembly: GuidAttribute("1A1B4852-D3E0-4ADC-9EDD-42A5D57652EA")] diff --git a/Bcfier.Navisworks/Properties/Resources.Designer.cs b/Bcfier.Navisworks/Properties/Resources.Designer.cs deleted file mode 100644 index d3fa2d8b..00000000 --- a/Bcfier.Navisworks/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Navisworks.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bcfier.Navisworks.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Bcfier.Navisworks/Properties/Resources.resx b/Bcfier.Navisworks/Properties/Resources.resx deleted file mode 100644 index af7dbebb..00000000 --- a/Bcfier.Navisworks/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bcfier.Navisworks/Properties/Settings.Designer.cs b/Bcfier.Navisworks/Properties/Settings.Designer.cs deleted file mode 100644 index b2e7acff..00000000 --- a/Bcfier.Navisworks/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Navisworks.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Bcfier.Navisworks/Properties/Settings.settings b/Bcfier.Navisworks/Properties/Settings.settings deleted file mode 100644 index 033d7a5e..00000000 --- a/Bcfier.Navisworks/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier.Navisworks/Windows/AddViewNavis.xaml b/Bcfier.Navisworks/Windows/AddViewNavis.xaml deleted file mode 100644 index c7b25660..00000000 --- a/Bcfier.Navisworks/Windows/AddViewNavis.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/Bcfier.Navisworks/Windows/AddViewNavis.xaml.cs b/Bcfier.Navisworks/Windows/AddViewNavis.xaml.cs deleted file mode 100644 index bcd908ca..00000000 --- a/Bcfier.Navisworks/Windows/AddViewNavis.xaml.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.IO; -using System.Windows; -using Bcfier.Bcf.Bcf2; -using Autodesk.Navisworks.Api; -using ComBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge; -using ComApi = Autodesk.Navisworks.Api.Interop.ComApi; -using System.Drawing; -using System.Drawing.Imaging; - -namespace Bcfier.Navisworks.Windows -{ - /// - /// Interaction logic for AddViewNavis.xaml - /// - public partial class AddViewNavis : Window - { - public AddViewNavis(Markup issue, string bcfTempFolder) - { - try - { - InitializeComponent(); - AddViewControl.Issue = issue; - AddViewControl.TempFolder = bcfTempFolder; - - AddViewControl.TextBlockInfo.Text = "3D information of the current view will be included in the viewpoint"; - - GetNavisSnapshot(); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error!"); - } - - } - - public void GetNavisSnapshot() - { - try - { - string tempImg = Path.Combine(Path.GetTempPath(), "BCFier", Path.GetTempFileName() + ".png"); - // get the state of COM - ComApi.InwOpState10 oState = ComBridge.State; - // get the IO plugin for image - ComApi.InwOaPropertyVec options = oState.GetIOPluginOptions("lcodpimage"); - //export the viewpoint to the image - oState.DriveIOPlugin("lcodpimage", tempImg, options); - Bitmap bitmap = new Bitmap(tempImg); - var imageStream = new MemoryStream(); - bitmap.Save(imageStream, ImageFormat.Jpeg); - bitmap.Dispose(); - - AddViewControl.AddViewpoint(tempImg); - File.Delete(tempImg); - - } - catch (Exception ex1) - { - MessageBox.Show("exception: " + ex1, "Error!",MessageBoxButton.OK,MessageBoxImage.Error); - } - } - } -} diff --git a/Bcfier.Navisworks/app.config b/Bcfier.Navisworks/app.config deleted file mode 100644 index 51278a45..00000000 --- a/Bcfier.Navisworks/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/Bcfier.Navisworks/en-US/RibbonDefinition.xaml b/Bcfier.Navisworks/en-US/RibbonDefinition.xaml deleted file mode 100644 index 7bce29dd..00000000 --- a/Bcfier.Navisworks/en-US/RibbonDefinition.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - diff --git a/Bcfier.Revit/AddIssueRevit.xaml b/Bcfier.Revit/AddIssueRevit.xaml deleted file mode 100644 index 2861bf39..00000000 --- a/Bcfier.Revit/AddIssueRevit.xaml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - diff --git a/Bcfier.Revit/AddIssueRevit.xaml.cs b/Bcfier.Revit/AddIssueRevit.xaml.cs deleted file mode 100644 index b394eac2..00000000 --- a/Bcfier.Revit/AddIssueRevit.xaml.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Diagnostics; -//using System.Drawing; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using System.IO; -using System.Collections.ObjectModel; -using Teocomi.Bcfier.Classes; - -namespace Teocomi.Bcfier.Revit -{ - /// - /// Interaction logic for AddIssueRevit.xaml - /// - public partial class AddIssueRevit : Window - { - public string snapshot; - Document doc = null; - UIDocument uidoc = null; - private string[] visuals = { "FlatColors", "HLR", "Realistic", "RealisticWithEdges", "Rendering", "Shading", "ShadingWithEdges", "Wireframe" }; - private string[] statuses = { "Error", "Warning", "Info", "Unknown" }; - - - public AddIssueRevit(UIDocument uidoc2, string folder) - { - try - { - uidoc = uidoc2; - doc = uidoc.Document; - - snapshot = System.IO.Path.Combine(folder, "snapshot.png"); - InitializeComponent(); - TitleBox.Focus(); - - comboVisuals.ItemsSource = visuals; - comboStatuses.ItemsSource = statuses; - comboStatuses.SelectedIndex = 3; - - - - - - //select current visual style - string currentV = doc.ActiveView.DisplayStyle.ToString(); - for (int i = 0; i < comboVisuals.Items.Count; i++) - { - if (comboVisuals.Items[i].ToString() == currentV) - { - comboVisuals.SelectedIndex = i; - } - - } - - - updateImage(); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - - } - - private void updateImage() - { - try - { - SnapshotImg.Source = null; - ImageExportOptions options = new ImageExportOptions(); - options.FilePath = snapshot; - // options. - options.HLRandWFViewsFileType = ImageFileType.PNG; - options.ShadowViewsFileType = ImageFileType.PNG; - options.ExportRange = ExportRange.VisibleRegionOfCurrentView; - options.ZoomType = ZoomFitType.FitToPage; - options.ImageResolution = ImageResolution.DPI_72; - options.PixelSize = 1000; - doc.ExportImage(options); - BitmapImage source = new BitmapImage(); - source.BeginInit(); - source.UriSource = new Uri(snapshot); - source.CacheOption = BitmapCacheOption.OnLoad; - source.CreateOptions = BitmapCreateOptions.IgnoreImageCache; - source.EndInit(); - SnapshotImg.Source = source; - - PathLabel.Content = "none"; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - - } - - private void comboVisuals_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - try - { - if (doc.ActiveView.DisplayStyle.ToString() != comboVisuals.SelectedValue.ToString()) - { - switch (comboVisuals.SelectedIndex) - { - case 0: - doc.ActiveView.DisplayStyle = DisplayStyle.FlatColors; - break; - case 1: - doc.ActiveView.DisplayStyle = DisplayStyle.HLR; - break; - case 2: - doc.ActiveView.DisplayStyle = DisplayStyle.Realistic; - break; - case 3: - doc.ActiveView.DisplayStyle = DisplayStyle.RealisticWithEdges; - break; - case 4: - doc.ActiveView.DisplayStyle = DisplayStyle.Rendering; - break; - case 5: - doc.ActiveView.DisplayStyle = DisplayStyle.Shading; - break; - case 6: - doc.ActiveView.DisplayStyle = DisplayStyle.ShadingWithEdges; - break; - case 7: - doc.ActiveView.DisplayStyle = DisplayStyle.Wireframe; - break; - default: - break; - } - - } - uidoc.RefreshActiveView(); - updateImage(); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - - } - - //LOAD EXTERNAL IMAGE - private void Button_LoadImage(object sender, RoutedEventArgs e) - { - - Microsoft.Win32.OpenFileDialog openFileDialog1 = new Microsoft.Win32.OpenFileDialog(); - // openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - openFileDialog1.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png"; - openFileDialog1.RestoreDirectory = true; - Nullable result = openFileDialog1.ShowDialog(); // Show the dialog. - - if (result == true) // Test result. - { - try - { - BitmapImage image = new BitmapImage(); - image.BeginInit(); - image.UriSource = new Uri(openFileDialog1.FileName); - image.CacheOption = BitmapCacheOption.OnLoad; - image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; - image.EndInit(); - BitmapSource a = ConvertBitmapTo96DPI(image); - int width = (int)a.Width; - int height = (int)a.Height; - if (width > 1500 || image.Height > 1500) - { - string size = width.ToString() + "x" + height.ToString(); - int newWidth = 1500; - float scale = (float)newWidth / ((float)width / (float)height); - int newHeight = Convert.ToInt32(scale); - - MessageBoxResult answer = MessageBox.Show("Image size is " + size + ", " - + "such a big image could increase A LOT the BCF file size. " - + "Do you want me to resize it to " + newWidth.ToString() + "x" + newHeight.ToString() + " for you?", "Attention!", - MessageBoxButton.YesNo, MessageBoxImage.Question); - if (answer == MessageBoxResult.Yes) - { - width = newWidth; - } - - /* - TaskDialog mainDialog = new TaskDialog("Attention!"); - mainDialog.MainInstruction = "Attention!"; - mainDialog.MainContent = - "Image size is " + size + ", " - + "such a big image could increase A LOT the BCF file size. " - + "Do you want me to resize it to " + newWidth.ToString() + "x" + newHeight.ToString() + " for you?"; - mainDialog.CommonButtons = TaskDialogCommonButtons.No ^ TaskDialogCommonButtons.Yes; - mainDialog.DefaultButton = TaskDialogResult.Yes; - TaskDialogResult tResult = mainDialog.Show(); - - //ONLY IF NECESSARY I RESIZE - if (TaskDialogResult.Yes == tResult) - { - width = newHeight; - }*/ - } - byte[] imageBytes = LoadImageData(openFileDialog1.FileName); - ImageSource imageSource = CreateImage(imageBytes, width, 0); - imageBytes = GetEncodedImageData(imageSource, ".jpg"); - SaveImageData(imageBytes, snapshot); - //VISUALIZE IMAGE - BitmapImage source = new BitmapImage(); - source.BeginInit(); - source.UriSource = new Uri(snapshot); - source.CacheOption = BitmapCacheOption.OnLoad; - source.CreateOptions = BitmapCreateOptions.IgnoreImageCache; - source.EndInit(); - SnapshotImg.Source = source; - PathLabel.Content = openFileDialog1.FileName; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - } - - public static BitmapSource ConvertBitmapTo96DPI(BitmapImage bitmapImage) - { - try - { - double dpi = 96; - int width = bitmapImage.PixelWidth; - int height = bitmapImage.PixelHeight; - - int stride = width * 4; // 4 bytes per pixel - byte[] pixelData = new byte[stride * height]; - bitmapImage.CopyPixels(pixelData, stride, 0); - - return BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride); - } - - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - return null; - } - - private static byte[] LoadImageData(string filePath) - { - try - { - FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); - BinaryReader br = new BinaryReader(fs); - byte[] imageBytes = br.ReadBytes((int)fs.Length); - br.Close(); - fs.Close(); - return imageBytes; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - return null; - } - - private static ImageSource CreateImage(byte[] imageData, int decodePixelWidth, int decodePixelHeight) - { - try - { - if (imageData == null) return null; - BitmapImage result = new BitmapImage(); - result.BeginInit(); - if (decodePixelWidth > 0) - { - result.DecodePixelWidth = decodePixelWidth; - } - if (decodePixelHeight > 0) - { - result.DecodePixelHeight = decodePixelHeight; - } - result.StreamSource = new MemoryStream(imageData); - result.CreateOptions = BitmapCreateOptions.None; - result.CacheOption = BitmapCacheOption.Default; - result.EndInit(); - return result; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - return null; - } - - private static void SaveImageData(byte[] imageData, string filePath) - { - try - { - FileStream fs = new FileStream(filePath, FileMode.Create, - FileAccess.Write); - BinaryWriter bw = new BinaryWriter(fs); - bw.Write(imageData); - bw.Close(); - fs.Close(); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - - internal byte[] GetEncodedImageData(ImageSource image, string preferredFormat) - { - try - { - byte[] result = null; - BitmapEncoder encoder = null; - switch (preferredFormat.ToLower()) - { - case ".jpg": - case ".jpeg": - encoder = new JpegBitmapEncoder(); - break; - case ".bmp": - encoder = new BmpBitmapEncoder(); - break; - case ".png": - encoder = new PngBitmapEncoder(); - break; - case ".tif": - case ".tiff": - encoder = new TiffBitmapEncoder(); - break; - case ".gif": - encoder = new GifBitmapEncoder(); - break; - case ".wmp": - encoder = new WmpBitmapEncoder(); - break; - } - if (image is BitmapSource) - { - MemoryStream stream = new MemoryStream(); - encoder.Frames.Add(BitmapFrame.Create(image as BitmapSource)); - encoder.Save(stream); - stream.Seek(0, SeekOrigin.Begin); - result = new byte[stream.Length]; - BinaryReader br = new BinaryReader(stream); - br.Read(result, 0, (int)stream.Length); - br.Close(); - stream.Close(); - } - return result; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - return null; - } - - private void Button_Cancel(object sender, RoutedEventArgs e) - { - DialogResult = false; - } - - private void Button_OK(object sender, RoutedEventArgs e) - { - if (string.IsNullOrWhiteSpace(TitleBox.Text)) - { - MessageBox.Show("Please insert an Issue Title.", "Title required", MessageBoxButton.OK, MessageBoxImage.Warning); - return; - } - DialogResult = true; - } - - private void EditSnapshot_Click(object sender, RoutedEventArgs e) - { - try - { - string editSnap = "mspaint"; - - if (File.Exists(snapshot)) - { - string customeditor = MySettings.Get("editSnap"); - if (!string.IsNullOrEmpty(customeditor) && File.Exists(customeditor)) - editSnap = customeditor; - - - Process paint = new Process(); - // paint.Start(editSnap, "\"" + snapshot + "\""); - ProcessStartInfo paintInfo = new ProcessStartInfo(editSnap, "\"" + snapshot + "\""); - - paintInfo.UseShellExecute = false; - //navisworksStartInfo.RedirectStandardOutput = true; - - paint.StartInfo = paintInfo; - paint.Start(); - - paint.WaitForExit(); - Refresh_Click(null, null); - - - } - else - MessageBox.Show("Snapshot is not a valit image, please try again.", "Error!", MessageBoxButton.OK, MessageBoxImage.Error); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - - private void Refresh_Click(object sender, RoutedEventArgs e) - { - try - { - BitmapImage source = new BitmapImage(); - source.BeginInit(); - source.UriSource = new Uri(snapshot); - source.CacheOption = BitmapCacheOption.OnLoad; - source.CreateOptions = BitmapCreateOptions.IgnoreImageCache; - source.EndInit(); - SnapshotImg.Source = source; - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - - - } -} diff --git a/Bcfier.Revit/AddViewRevit.xaml b/Bcfier.Revit/AddViewRevit.xaml deleted file mode 100644 index d77f21b1..00000000 --- a/Bcfier.Revit/AddViewRevit.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/Bcfier.Revit/AddViewRevit.xaml.cs b/Bcfier.Revit/AddViewRevit.xaml.cs deleted file mode 100644 index 8297ea5a..00000000 --- a/Bcfier.Revit/AddViewRevit.xaml.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.IO; -using System.Windows; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using Bcfier.Bcf.Bcf2; - -namespace Bcfier.Revit -{ - /// - /// Interaction logic for AddViewRevit.xaml - /// - public partial class AddViewRevit : Window - { - - private Document doc = null; - - public AddViewRevit(Markup issue, string bcfTempFolder, Document _doc) - { - try - { - this.InitializeComponent(); - AddViewControl.Issue = issue; - AddViewControl.TempFolder = bcfTempFolder; - doc = _doc; - - AddViewControl.TextBlockInfo.Text = "3D/2D information of the current view will be included in the viewpoint"; - - GetRevitSnapshot(); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - - } - - private void GetRevitSnapshot() - { - try - { - string tempImg = Path.Combine(Path.GetTempPath(), "BCFier", Path.GetTempFileName() + ".png"); - var options = new ImageExportOptions - { - FilePath = tempImg, - HLRandWFViewsFileType = ImageFileType.PNG, - ShadowViewsFileType = ImageFileType.PNG, - ExportRange = ExportRange.VisibleRegionOfCurrentView, - ZoomType = ZoomFitType.FitToPage, - ImageResolution = ImageResolution.DPI_72, - PixelSize = 1000 - }; - doc.ExportImage(options); - - AddViewControl.AddViewpoint(tempImg); - File.Delete(tempImg); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - - } -} \ No newline at end of file diff --git a/Bcfier.Revit/App.config b/Bcfier.Revit/App.config deleted file mode 100644 index 0c7ae12f..00000000 --- a/Bcfier.Revit/App.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Bcfier.Revit/Assets/icon.ico b/Bcfier.Revit/Assets/icon.ico deleted file mode 100644 index 6a2bf0a3..00000000 Binary files a/Bcfier.Revit/Assets/icon.ico and /dev/null differ diff --git a/Bcfier.Revit/Bcfier.Revit.addin b/Bcfier.Revit/Bcfier.Revit.addin deleted file mode 100644 index 3cac2332..00000000 --- a/Bcfier.Revit/Bcfier.Revit.addin +++ /dev/null @@ -1,11 +0,0 @@ - - - - BCFier for Revit - Bcfier.Revit\Bcfier.Revit.dll - 0d553633-80f8-490b-84d6-9d3d6ad4196d - Bcfier.Revit.Entry.AppMain - TEOC - Matteo Cominetti, http://bcfier.com - - \ No newline at end of file diff --git a/Bcfier.Revit/Bcfier.Revit.csproj b/Bcfier.Revit/Bcfier.Revit.csproj deleted file mode 100644 index 4b768c49..00000000 --- a/Bcfier.Revit/Bcfier.Revit.csproj +++ /dev/null @@ -1,605 +0,0 @@ - - - - - Debug - AnyCPU - {2D132990-5674-42DF-93BF-55BA8FDC6A23} - Library - Properties - Bcfier.Revit - Bcfier.Revit - v4.7 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - - Program - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - true - bin\Debug-2015\ - TRACE;DEBUG;Version2015 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2015 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2015\Revit.exe - v4.5 - - - bin\Release-2015\ - TRACE;RELEASE;Version2015 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2015 - $(AssemblyName) - 0 - - None - - false - v4.5 - - - - true - bin\Debug-2016\ - TRACE;DEBUG;Version2016 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2016 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2016\Revit.exe - v4.5 - - - bin\Release-2016\ - TRACE;RELEASE;Version2016 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2016 - $(AssemblyName) - 0 - - None - - false - v4.5 - - - - true - bin\Debug-2017\ - TRACE;DEBUG;Version2017 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2017 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2017\Revit.exe - v4.6 - - - bin\Release-2017\ - TRACE;RELEASE;Version2017 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2017 - $(AssemblyName) - 0 - - None - - false - v4.6 - - - - true - bin\Debug-2018\ - TRACE;DEBUG;Version2018 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2018 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2018\Revit.exe - v4.6 - - - bin\Release-2018\ - TRACE;RELEASE;Version2018 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2018 - $(AssemblyName) - 0 - - None - - false - v4.6 - - - - true - bin\Debug-2019\ - TRACE;DEBUG;Version2019 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2019 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2019\Revit.exe - v4.7.2 - - - bin\Release-2019\ - TRACE;RELEASE;Version2019 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2019 - $(AssemblyName) - 0 - - None - - false - v4.7.2 - - - - bin\Release-2020\ - TRACE;RELEASE;Version2020 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2020 - $(AssemblyName) - 0 - - None - - false - v4.7.2 - - - true - bin\Debug-2020\ - TRACE;DEBUG;Version2020 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2020 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2020\Revit.exe - v4.7.2 - - - - true - bin\Debug-2021\ - TRACE;DEBUG;Version2021 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2021 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2021\Revit.exe - v4.8 - - - bin\Release-2021\ - TRACE;RELEASE;Version2021 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2021 - $(AssemblyName) - 0 - - None - - false - v4.8 - - - - true - bin\Debug-2022\ - TRACE;DEBUG;Version2022 - full - x64 - prompt - MinimumRecommendedRules.ruleset - 2022 - $(AssemblyName) - false - Program - C:\Program Files\Autodesk\Revit 2022\Revit.exe - v4.8 - - - bin\Release-2022\ - TRACE;RELEASE;Version2022 - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - 2022 - $(AssemblyName) - 0 - - None - - false - v4.8 - - - - - - - - - - - C:\Program Files\Autodesk\Revit 2017\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2017\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2017\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2018\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2018\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2018\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2019\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2020\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2020\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2021\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2021\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2021\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2022\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2022\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2022\RevitAPIIFC.dll - False - - - - - C:\Program Files\Autodesk\Revit 2015\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2015\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2015\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2016\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2016\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2017\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2017\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2017\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2018\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2018\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2018\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2019\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2020\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2020\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2021\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2021\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2021\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2022\RevitAPI.dll - False - - - C:\Program Files\Autodesk\Revit 2022\RevitAPIUI.dll - False - - - C:\Program Files\Autodesk\Revit 2022\RevitAPIIFC.dll - False - - - - C:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll - - - - - - - 4.0 - - - - - - - - Properties\AssemblyVersionInfo.cs - - - AddViewRevit.xaml - - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - - - - - - RevitWindow.xaml - Code - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - Always - - - - - - - - {503ce2c1-09d7-4f15-bb42-86196ee01ed4} - Bcfier - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier.Revit/Data/RevitUtils.cs b/Bcfier.Revit/Data/RevitUtils.cs deleted file mode 100644 index 01ff2dea..00000000 --- a/Bcfier.Revit/Data/RevitUtils.cs +++ /dev/null @@ -1,115 +0,0 @@ -using Autodesk.Revit.DB; -using Bcfier.Bcf.Bcf2; -using System; -using Point = Bcfier.Bcf.Bcf2.Point; - -namespace Bcfier.Revit.Data -{ - public static class RevitUtils - { - /// - //MOVES THE CAMERA ACCORDING TO THE PROJECT BASE LOCATION - //function that changes the coordinates accordingly to the project base location to an absolute location (for BCF export) - //if the value negative is set to true, does the opposite (for opening BCF views) - /// - /// center - /// view direction - /// up direction - /// convert to/from - /// - public static ViewOrientation3D ConvertBasePoint(Document doc, XYZ c, XYZ view, XYZ up, bool negative) - { - double angle = 0; - double x = 0; - double y = 0; - double z = 0; - - //VERY IMPORTANT - //BuiltInParameter.BASEPOINT_EASTWEST_PARAM is the value of the BASE POINT LOCATION - //position is the location of the BPL related to Revit's absolute origin - //if BPL is set to 0,0,0 not always it corresponds to Revit's origin - - XYZ origin = new XYZ(0, 0, 0); -#if Version2019 || Version2020 || Version2021 || Version2022 - ProjectPosition position = doc.ActiveProjectLocation.GetProjectPosition(origin); -#else - ProjectPosition position = doc.ActiveProjectLocation.get_ProjectPosition(origin); -#endif - - int i = (negative) ? -1 : 1; - - x = i * position.EastWest; - y = i * position.NorthSouth; - z = i * position.Elevation; - angle = i * position.Angle; - - if (negative) // I do the addition BEFORE - c = new XYZ(c.X + x, c.Y + y, c.Z + z); - - //rotation - double centX = (c.X * Math.Cos(angle)) - (c.Y * Math.Sin(angle)); - double centY = (c.X * Math.Sin(angle)) + (c.Y * Math.Cos(angle)); - - XYZ newC = new XYZ(); - if (negative) - newC = new XYZ(centX, centY, c.Z); - else // I do the addition AFTERWARDS - newC = new XYZ(centX + x, centY + y, c.Z + z); - - - double viewX = (view.X * Math.Cos(angle)) - (view.Y * Math.Sin(angle)); - double viewY = (view.X * Math.Sin(angle)) + (view.Y * Math.Cos(angle)); - XYZ newView = new XYZ(viewX, viewY, view.Z); - - double upX = (up.X * Math.Cos(angle)) - (up.Y * Math.Sin(angle)); - double upY = (up.X * Math.Sin(angle)) + (up.Y * Math.Cos(angle)); - - XYZ newUp = new XYZ(upX, upY, up.Z); - return new ViewOrientation3D(newC, newUp, newView); - } - - public static XYZ GetRevitXYZ(double X, double Y, double Z) - { - return new XYZ(X.ToFeet(), Y.ToFeet(), Z.ToFeet()); - } - - public static XYZ GetRevitXYZ(Direction d) - { - return new XYZ(d.X.ToFeet(), d.Y.ToFeet(), d.Z.ToFeet()); - } - - public static XYZ GetRevitXYZ(Point d) - { - return new XYZ(d.X.ToFeet(), d.Y.ToFeet(), d.Z.ToFeet()); - } - - /// - /// Converts feet units to meters - /// - /// Value in feet to be converted to meters - /// - public static double ToMeters(this double feet) - { -#if Version2021 || Version2022 - return UnitUtils.ConvertFromInternalUnits(feet, UnitTypeId.Meters); -#else - return UnitUtils.ConvertFromInternalUnits(feet, DisplayUnitType.DUT_METERS); -#endif - } - /// - /// Converts meters units to feet - /// - /// Value in feet to be converted to feet - /// - public static double ToFeet(this double meters) - { -#if Version2021 || Version2022 - return UnitUtils.ConvertToInternalUnits(meters, UnitTypeId.Meters); -#else - return UnitUtils.ConvertToInternalUnits(meters, DisplayUnitType.DUT_METERS); -#endif - - } - } - -} diff --git a/Bcfier.Revit/Data/RevitView.cs b/Bcfier.Revit/Data/RevitView.cs deleted file mode 100644 index bcc457a5..00000000 --- a/Bcfier.Revit/Data/RevitView.cs +++ /dev/null @@ -1,215 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using Bcfier.Bcf.Bcf2; -using Bcfier.Data.Utils; -using Point = Bcfier.Bcf.Bcf2.Point; - -namespace Bcfier.Revit.Data -{ - //Methods for working with views - public static class RevitView - { - // - //Generate a VisualizationInfo of the current view - // - // - public static VisualizationInfo GenerateViewpoint(UIDocument uidoc) - { - try - { - var doc = uidoc.Document; - - var v = new VisualizationInfo(); - - //Corners of the active UI view - var topLeft = uidoc.GetOpenUIViews()[0].GetZoomCorners()[0]; - var bottomRight = uidoc.GetOpenUIViews()[0].GetZoomCorners()[1]; - - //It's a 2D view - //not supported by BCF, but I store it under a custom - //fields using 2D coordinates and sheet id - //and sheet name - if (uidoc.ActiveView.ViewType != ViewType.ThreeD) - { - v.SheetCamera = new SheetCamera - { - SheetID = uidoc.ActiveView.Id.IntegerValue, - SheetName = uidoc.ActiveView.Name, - TopLeft = new Point { X = topLeft.X, Y = topLeft.Y, Z = topLeft.Z }, - BottomRight = new Point { X = bottomRight.X, Y = bottomRight.Y, Z = bottomRight.Z } - }; - } - //It's a 3d view - else - { - var viewCenter = new XYZ(); - var view3D = (View3D)uidoc.ActiveView; - double zoomValue = 1; - // it is a orthogonal view - if (!view3D.IsPerspective) - { - double x = (topLeft.X + bottomRight.X) / 2; - double y = (topLeft.Y + bottomRight.Y) / 2; - double z = (topLeft.Z + bottomRight.Z) / 2; - //center of the UI view - viewCenter = new XYZ(x, y, z); - - //vector going from BR to TL - XYZ diagVector = topLeft.Subtract(bottomRight); - //length of the vector - double dist = topLeft.DistanceTo(bottomRight) / 2; - - //ViewToWorldScale value - zoomValue = dist * Math.Sin(diagVector.AngleTo(view3D.RightDirection)).ToMeters(); - - // **** CUSTOM VALUE FOR TEKLA **** // - // calculated experimentally, not sure why but it works - //if (UserSettings.Get("optTekla") == "1") - // zoomValue = zoomValue * 2.5; - // **** CUSTOM VALUE FOR TEKLA **** // - - ViewOrientation3D t = RevitUtils.ConvertBasePoint(doc, viewCenter, uidoc.ActiveView.ViewDirection, - uidoc.ActiveView.UpDirection, false); - - XYZ c = t.EyePosition; - XYZ vi = t.ForwardDirection; - XYZ up = t.UpDirection; - - - v.OrthogonalCamera = new OrthogonalCamera - { - CameraViewPoint = - { - X = c.X.ToMeters(), - Y = c.Y.ToMeters(), - Z = c.Z.ToMeters() - }, - CameraUpVector = - { - X = up.X.ToMeters(), - Y = up.Y.ToMeters(), - Z = up.Z.ToMeters() - }, - CameraDirection = - { - X = vi.X.ToMeters() * -1, - Y = vi.Y.ToMeters() * -1, - Z = vi.Z.ToMeters() * -1 - }, - ViewToWorldScale = zoomValue - }; - } - // it is a perspective view - else - { - viewCenter = uidoc.ActiveView.Origin; - //revit default value - zoomValue = 45; - - ViewOrientation3D t = RevitUtils.ConvertBasePoint(doc, viewCenter, uidoc.ActiveView.ViewDirection, - uidoc.ActiveView.UpDirection, false); - - XYZ c = t.EyePosition; - XYZ vi = t.ForwardDirection; - XYZ up = t.UpDirection; - - v.PerspectiveCamera = new PerspectiveCamera - { - CameraViewPoint = - { - X = c.X.ToMeters(), - Y = c.Y.ToMeters(), - Z = c.Z.ToMeters() - }, - CameraUpVector = - { - X = up.X.ToMeters(), - Y = up.Y.ToMeters(), - Z = up.Z.ToMeters() - }, - CameraDirection = - { - X = vi.X.ToMeters() * -1, - Y = vi.Y.ToMeters() * -1, - Z = vi.Z.ToMeters() * -1 - }, - FieldOfView = zoomValue - }; - } - - } - //COMPONENTS PART - string versionName = doc.Application.VersionName; - v.Components = new Components(); - - var visibleElems = new FilteredElementCollector(doc, doc.ActiveView.Id) - .WhereElementIsNotElementType() - .WhereElementIsViewIndependent() - .ToElementIds(); - var hiddenElems = new FilteredElementCollector(doc) - .WhereElementIsNotElementType() - .WhereElementIsViewIndependent() - .Where(x => x.IsHidden(doc.ActiveView) - || !doc.ActiveView.IsElementVisibleInTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate, x.Id)).Select(x=>x.Id) - ;//would need to check how much this is affecting performance - - var selectedElems = uidoc.Selection.GetElementIds(); - - v.Components = new Components(); - v.Components.Visibility = new ComponentVisibility(); - - //TODO: set ViewSetupHints - //TODO: create clipping planes - //list of hidden components is smaller than the list of visible components - if (visibleElems.Count() > hiddenElems.Count()) - { - v.Components.Visibility.DefaultVisibility = true; - v.Components.Visibility.DefaultVisibilitySpecified = true; - v.Components.Visibility.Exceptions = hiddenElems.Select(x => new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, x)), - AuthoringToolId = x.IntegerValue.ToString() - }).ToArray(); - - } - //list of visible components is smaller or equals the list of hidden components - else - { - v.Components.Visibility.DefaultVisibility = false; - v.Components.Visibility.DefaultVisibilitySpecified = true; - v.Components.Visibility.Exceptions = visibleElems.Select(x => new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, x)), - AuthoringToolId = x.IntegerValue.ToString() - }).ToArray(); - } - - //selected elements - v.Components.Selection = selectedElems.Select(x => new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, x)), - AuthoringToolId = x.IntegerValue.ToString() - }).ToArray(); - - - - return v; - - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error generating viewpoint", "exception: " + ex1); - } - return null; - } - - } -} diff --git a/Bcfier.Revit/Entry/AppMain.cs b/Bcfier.Revit/Entry/AppMain.cs deleted file mode 100644 index 2aa13c0a..00000000 --- a/Bcfier.Revit/Entry/AppMain.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using Autodesk.Revit.Attributes; -using Autodesk.Revit.UI; - -namespace Bcfier.Revit.Entry -{ - - [Transaction(TransactionMode.Manual)] - public class AppMain : IExternalApplication - { - private string _path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - #region Revit IExternalApplciation Implementation - - /// - /// Startup - /// - /// - /// - public Result OnStartup(UIControlledApplication application) - { - try - { - // Tab - RibbonPanel panel = application.CreateRibbonPanel("BCFier"); - - // Button Data - PushButton pushButton = panel.AddItem(new PushButtonData("BCFier", - "BCFier " + Assembly.GetExecutingAssembly().GetName().Version, - Path.Combine(_path, "Bcfier.Revit.dll"), - "Bcfier.Revit.Entry.CmdMain")) as PushButton; - - // Images and Tooltip - if (pushButton != null) - { - pushButton.Image = LoadPngImgSource("Bcfier.Assets.BCFierIcon16x16.png", Path.Combine(_path, "Bcfier.dll")); - pushButton.LargeImage = LoadPngImgSource("Bcfier.Assets.BCFierIcon32x32.png", Path.Combine(_path, "Bcfier.dll")); - pushButton.ToolTip = "BCFier"; - } - } - catch (Exception ex1) - { - MessageBox.Show("exception: " + ex1); - return Result.Failed; - } - - return Result.Succeeded; - } - - /// - /// Shut Down - /// - /// - /// - public Result OnShutdown(UIControlledApplication application) - { - return Result.Succeeded; - } - - #endregion - - #region Private Members - - /// - /// Get System Architecture - /// - /// - static string ProgramFilesx86() - { - if (8 == IntPtr.Size || (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432")))) - return Environment.GetEnvironmentVariable("ProgramFiles(x86)"); - - return Environment.GetEnvironmentVariable("ProgramFiles"); - } - - - /// - /// Load an Image Source from File - /// - /// - /// - /// - private ImageSource LoadPngImgSource(string sourceName, string path) - { - - try - { - // Assembly & Stream - var assembly = Assembly.LoadFrom(Path.Combine(path)); - var icon = assembly.GetManifestResourceStream(sourceName); - - // Decoder - PngBitmapDecoder m_decoder = new PngBitmapDecoder(icon, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); - - // Source - ImageSource m_source = m_decoder.Frames[0]; - return (m_source); - - } - catch { } - - // Fail - return null; - - } - - #endregion - - } -} \ No newline at end of file diff --git a/Bcfier.Revit/Entry/CmdMain.cs b/Bcfier.Revit/Entry/CmdMain.cs deleted file mode 100644 index 8c5e7145..00000000 --- a/Bcfier.Revit/Entry/CmdMain.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Autodesk.Revit.Attributes; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using System; -using System.Reflection; - -namespace Bcfier.Revit.Entry -{ - - /// - /// Obfuscation Ignore for External Interface - /// - [Obfuscation(Exclude = true, ApplyToMembers = false)] - [Transaction(TransactionMode.Manual)] - [Regeneration(RegenerationOption.Manual)] - public class CmdMain : IExternalCommand - { - -#if Version2022 - public const string RevitVersion = "2022"; -#elif Version2021 - public const string RevitVersion = "2021"; -#elif Version2020 - public const string RevitVersion = "2020"; -#elif Version2019 - - public const string RevitVersion = "2019"; - -#elif Version2018 - - public const string RevitVersion = "2018"; - -#elif Version2017 - - public const string RevitVersion = "2017"; - -#elif Version2016 - - public const string RevitVersion = "2016"; - -#elif Version2015 - - public const string RevitVersion = "2015"; - - -#endif - - - - internal static CmdMain ThisCmd = null; - private static bool _isRunning; - private static ExtAppBcfier _extAppBcfier; - - /// - /// Main Command Entry Point - /// - /// - /// - /// - /// - public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) - { - try - { - - //Version check - - if (!commandData.Application.Application.VersionName.Contains(RevitVersion)) - { - using (var td = new TaskDialog("Untested version")) - { - td.TitleAutoPrefix = false; - td.MainInstruction = "Untested Revit Version"; - td.MainContent = "This Add-In was built and tested only for Revit " + RevitVersion + ", proceed at your own risk"; - td.Show(); - } - } - - // Form Running? - if (_isRunning && _extAppBcfier != null && _extAppBcfier.RvtWindow.IsLoaded) - { - _extAppBcfier.Focus(); - return Result.Succeeded; - } - - _isRunning = true; - - ThisCmd = this; - _extAppBcfier = new ExtAppBcfier(); - _extAppBcfier.ShowForm(commandData.Application); - return Result.Succeeded; - - } - catch (Exception e) - { - message = e.Message; - return Result.Failed; - } - - } - - } -} \ No newline at end of file diff --git a/Bcfier.Revit/Entry/ExtAppBcfier.cs b/Bcfier.Revit/Entry/ExtAppBcfier.cs deleted file mode 100644 index fec9d0d2..00000000 --- a/Bcfier.Revit/Entry/ExtAppBcfier.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Reflection; -using Autodesk.Revit.Attributes; -using Autodesk.Revit.UI; -using System; -using System.Windows; - -namespace Bcfier.Revit.Entry -{ - - /// - /// Obfuscation Ignore for External Interface - /// - [Obfuscation(Exclude = true, ApplyToMembers = false)] - [Transaction(TransactionMode.Manual)] - public class ExtAppBcfier : IExternalApplication - { - - // class instance - public static ExtAppBcfier This = null; - // ModelessForm instance - public RevitWindow RvtWindow; - - #region Revit IExternalApplication Implementation - - /// - /// Startup - /// - /// - /// - public Result OnStartup(UIControlledApplication application) - { - RvtWindow = null; // no dialog needed yet; the command will bring it - This = this; // static access to this application instance - - return Result.Succeeded; - } - - /// - /// Shut Down - /// - /// - /// - public Result OnShutdown(UIControlledApplication application) - { - if (RvtWindow != null && RvtWindow.IsVisible) - { - RvtWindow.Close(); - } - - return Result.Succeeded; - } - - #endregion - - #region public methods - /// - /// The external command invokes this on the end-user's request - /// - /// - public void ShowForm(UIApplication uiapp) - { - try - { - // If we do not have a dialog yet, create and show it - if (RvtWindow != null) return; - - // A new handler to handle request posting by the dialog - var handler = new ExtEvntOpenView(); - - // External Event for the dialog to use (to post requests) - var extEvent = ExternalEvent.Create(handler); - - // We give the objects to the new dialog; - // The dialog becomes the owner responsible for disposing them, eventually. - RvtWindow = new RevitWindow(uiapp, extEvent, handler); - RvtWindow.Show(); - } - catch (Exception ex) - { - MessageBox.Show(ex.ToString()); - } - } - - /// - /// Set Focus - /// - public void Focus() - { - try - { - if (RvtWindow == null) return; - RvtWindow.Activate(); - RvtWindow.WindowState = WindowState.Normal; - } - catch (Exception ex) - { - MessageBox.Show(ex.ToString()); - } - - } - #endregion - } - -} \ No newline at end of file diff --git a/Bcfier.Revit/Entry/ExtEvntOpenView.cs b/Bcfier.Revit/Entry/ExtEvntOpenView.cs deleted file mode 100644 index 6ee2539e..00000000 --- a/Bcfier.Revit/Entry/ExtEvntOpenView.cs +++ /dev/null @@ -1,290 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Linq; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Windows; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using Bcfier.Bcf.Bcf2; -using Bcfier.Data.Utils; -using Bcfier.Revit.Data; - -namespace Bcfier.Revit.Entry -{ - /// - /// Obfuscation Ignore for External Interface - /// - public class ExtEvntOpenView : IExternalEventHandler - { - public VisualizationInfo v; - - /// - /// External Event Implementation - /// - /// - public void Execute(UIApplication app) - { - try - { - UIDocument uidoc = app.ActiveUIDocument; - Document doc = uidoc.Document; - var uniqueView = UserSettings.GetBool("alwaysNewView"); - - // IS ORTHOGONAL - if (v.OrthogonalCamera != null) - { - if (v.OrthogonalCamera.CameraViewPoint == null || v.OrthogonalCamera.CameraUpVector == null || v.OrthogonalCamera.CameraDirection == null) - return; - //type = "OrthogonalCamera"; - var zoom = v.OrthogonalCamera.ViewToWorldScale.ToFeet(); - var cameraDirection = RevitUtils.GetRevitXYZ(v.OrthogonalCamera.CameraDirection); - var cameraUpVector = RevitUtils.GetRevitXYZ(v.OrthogonalCamera.CameraUpVector); - var cameraViewPoint = RevitUtils.GetRevitXYZ(v.OrthogonalCamera.CameraViewPoint); - var orient3D = RevitUtils.ConvertBasePoint(doc, cameraViewPoint, cameraDirection, cameraUpVector, true); - - View3D orthoView = null; - //if active view is 3d ortho use it - if (doc.ActiveView.ViewType == ViewType.ThreeD) - { - var activeView3D = doc.ActiveView as View3D; - if (!activeView3D.IsPerspective) - orthoView = activeView3D; - } - if (orthoView == null) - { - //try to use an existing 3D view - IEnumerable viewcollector3D = get3DViews(doc); - if (viewcollector3D.Any(o => o.Name == "{3D}" || o.Name == "BCFortho")) - orthoView = viewcollector3D.First(o => o.Name == "{3D}" || o.Name == "BCFortho"); - } - using (var trans = new Transaction(uidoc.Document)) - { - if (trans.Start("Open orthogonal view") == TransactionStatus.Started) - { - //create a new 3d ortho view - - if (orthoView == null || uniqueView) - { - orthoView = View3D.CreateIsometric(doc, getFamilyViews(doc).First().Id); - orthoView.Name = (uniqueView) ? "BCFortho" + DateTime.Now.ToString("yyyyMMddTHHmmss") : "BCFortho"; - } - else - { - //reusing an existing view, I net to reset the visibility - //placed this here because if set afterwards it doesn't work - orthoView.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate); - } - orthoView.SetOrientation(orient3D); - trans.Commit(); - } - } - uidoc.ActiveView = orthoView; - //adjust view rectangle - - // **** CUSTOM VALUE FOR TEKLA **** // - // double x = zoom / 2.5; - // **** CUSTOM VALUE FOR TEKLA **** // - - double x = zoom; - //if(MySettings.Get("optTekla")=="1") - // x = zoom / 2.5; - - //set UI view position and zoom - XYZ m_xyzTl = uidoc.ActiveView.Origin.Add(uidoc.ActiveView.UpDirection.Multiply(x)).Subtract(uidoc.ActiveView.RightDirection.Multiply(x)); - XYZ m_xyzBr = uidoc.ActiveView.Origin.Subtract(uidoc.ActiveView.UpDirection.Multiply(x)).Add(uidoc.ActiveView.RightDirection.Multiply(x)); - uidoc.GetOpenUIViews().First().ZoomAndCenterRectangle(m_xyzTl, m_xyzBr); - } - //perspective - else if (v.PerspectiveCamera != null) - { - if (v.PerspectiveCamera.CameraViewPoint == null || v.PerspectiveCamera.CameraUpVector == null || v.PerspectiveCamera.CameraDirection == null) - return; - - //not used since the fov cannot be changed in Revit - var zoom = v.PerspectiveCamera.FieldOfView; - //FOV - not used - //double z1 = 18 / Math.Tan(zoom / 2 * Math.PI / 180); - //double z = 18 / Math.Tan(25 / 2 * Math.PI / 180); - //double factor = z1 - z; - - var cameraDirection = RevitUtils.GetRevitXYZ(v.PerspectiveCamera.CameraDirection); - var cameraUpVector = RevitUtils.GetRevitXYZ(v.PerspectiveCamera.CameraUpVector); - var cameraViewPoint = RevitUtils.GetRevitXYZ(v.PerspectiveCamera.CameraViewPoint); - var orient3D = RevitUtils.ConvertBasePoint(doc, cameraViewPoint, cameraDirection, cameraUpVector, true); - - - - View3D perspView = null; - //try to use an existing 3D view - IEnumerable viewcollector3D = get3DViews(doc); - if (viewcollector3D.Any(o => o.Name == "BCFpersp")) - perspView = viewcollector3D.First(o => o.Name == "BCFpersp"); - - using (var trans = new Transaction(uidoc.Document)) - { - if (trans.Start("Open perspective view") == TransactionStatus.Started) - { - if (null == perspView || uniqueView) - { - perspView = View3D.CreatePerspective(doc, getFamilyViews(doc).First().Id); - perspView.Name = (uniqueView) ? "BCFpersp" + DateTime.Now.ToString("yyyyMMddTHHmmss") : "BCFpersp"; - } - else - { - //reusing an existing view, I net to reset the visibility - //placed this here because if set afterwards it doesn't work - perspView.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate); - } - - perspView.SetOrientation(orient3D); - - // turn off the far clip plane - if (perspView.get_Parameter(BuiltInParameter.VIEWER_BOUND_ACTIVE_FAR).HasValue) - { - Parameter m_farClip = perspView.get_Parameter(BuiltInParameter.VIEWER_BOUND_ACTIVE_FAR); - m_farClip.Set(0); - } - perspView.CropBoxActive = true; - perspView.CropBoxVisible = true; - - trans.Commit(); - } - } - uidoc.ActiveView = perspView; - } - //sheet - else if (v.SheetCamera != null) - { - IEnumerable viewcollectorSheet = getSheets(doc, v.SheetCamera.SheetID, v.SheetCamera.SheetName); - if (!viewcollectorSheet.Any()) - { - - MessageBox.Show("View " + v.SheetCamera.SheetName + " with Id=" + v.SheetCamera.SheetID + " not found."); - return; - } - uidoc.ActiveView = viewcollectorSheet.First(); - uidoc.RefreshActiveView(); - - XYZ m_xyzTl = new XYZ(v.SheetCamera.TopLeft.X, v.SheetCamera.TopLeft.Y, v.SheetCamera.TopLeft.Z); - XYZ m_xyzBr = new XYZ(v.SheetCamera.BottomRight.X, v.SheetCamera.BottomRight.Y, v.SheetCamera.BottomRight.Z); - uidoc.GetOpenUIViews().First().ZoomAndCenterRectangle(m_xyzTl, m_xyzBr); - - } - //no view included - else - return; - - if (v.Components == null) - return; - - - var elementsToSelect = new List(); - var elementsToHide = new List(); - var elementsToShow = new List(); - - var visibleElems = new FilteredElementCollector(doc, doc.ActiveView.Id) - .WhereElementIsNotElementType() - .WhereElementIsViewIndependent() - .ToElementIds() - .Where(e => doc.GetElement(e).CanBeHidden(doc.ActiveView)); //might affect performance, but it's necessary - - - bool canSetVisibility = (v.Components.Visibility != null && - v.Components.Visibility.DefaultVisibilitySpecified && - v.Components.Visibility.Exceptions.Any()) - ; - bool canSetSelection = (v.Components.Selection != null && v.Components.Selection.Any()); - - - - //loop elements - foreach (var e in visibleElems) - { - var guid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, e)); - - if (canSetVisibility) - { - if (v.Components.Visibility.DefaultVisibility) - { - if (v.Components.Visibility.Exceptions.Any(x => x.IfcGuid == guid)) - elementsToHide.Add(e); - } - else - { - if (v.Components.Visibility.Exceptions.Any(x => x.IfcGuid == guid)) - elementsToShow.Add(e); - } - } - - if (canSetSelection) - { - if (v.Components.Selection.Any(x => x.IfcGuid == guid)) - elementsToSelect.Add(e); - } - } - - - - - - using (var trans = new Transaction(uidoc.Document)) - { - if (trans.Start("Apply BCF visibility and selection") == TransactionStatus.Started) - { - if (elementsToHide.Any()) - doc.ActiveView.HideElementsTemporary(elementsToHide); - //there are no items to hide, therefore hide everything and just show the visible ones - else if (elementsToShow.Any()) - doc.ActiveView.IsolateElementsTemporary(elementsToShow); - - if (elementsToSelect.Any()) - uidoc.Selection.SetElementIds(elementsToSelect); - } - trans.Commit(); - } - - - uidoc.RefreshActiveView(); - } - catch (Exception ex) - { - TaskDialog.Show("Error!", "exception: " + ex); - } - } - private IEnumerable getFamilyViews(Document doc) - { - - return from elem in new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)) - let type = elem as ViewFamilyType - where type.ViewFamily == ViewFamily.ThreeDimensional - select type; - } - private IEnumerable get3DViews(Document doc) - { - return from elem in new FilteredElementCollector(doc).OfClass(typeof(View3D)) - let view = elem as View3D - select view; - } - private IEnumerable getSheets(Document doc, int id, string stname) - { - ElementId eid = new ElementId(id); - return from elem in new FilteredElementCollector(doc).OfClass(typeof(View)) - let view = elem as View - //Get the view with the given Id or given name - where view.Id == eid | view.Name == stname - select view; - - } - - - - - public string GetName() - { - return "Open 3D View"; - } - // returns XYZ and ZOOM/FOV value - } - -} \ No newline at end of file diff --git a/Bcfier.Revit/Properties/AssemblyInfo.cs b/Bcfier.Revit/Properties/AssemblyInfo.cs deleted file mode 100755 index ef88330b..00000000 --- a/Bcfier.Revit/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bcfier.Revit")] -[assembly: AssemblyDescription("Bcfier.Revit")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("teocomi")] -[assembly: AssemblyProduct("Bcfier.Revit")] -[assembly: AssemblyCopyright("Copyright © teocomi 2017")] -[assembly: AssemblyTrademark("teocomi")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.ExternalAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - -[assembly: GuidAttribute("59068325-ACDC-4DB3-892A-1C90C9434BF8")] diff --git a/Bcfier.Revit/Properties/Resources.Designer.cs b/Bcfier.Revit/Properties/Resources.Designer.cs deleted file mode 100644 index 809ce116..00000000 --- a/Bcfier.Revit/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Revit.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bcfier.Revit.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Bcfier.Revit/Properties/Resources.resx b/Bcfier.Revit/Properties/Resources.resx deleted file mode 100644 index af7dbebb..00000000 --- a/Bcfier.Revit/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bcfier.Revit/Properties/Settings.Designer.cs b/Bcfier.Revit/Properties/Settings.Designer.cs deleted file mode 100644 index c35c5dff..00000000 --- a/Bcfier.Revit/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Revit.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Bcfier.Revit/Properties/Settings.settings b/Bcfier.Revit/Properties/Settings.settings deleted file mode 100644 index 033d7a5e..00000000 --- a/Bcfier.Revit/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier.Revit/RevitWindow.xaml b/Bcfier.Revit/RevitWindow.xaml deleted file mode 100755 index 0fe07cb2..00000000 --- a/Bcfier.Revit/RevitWindow.xaml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - diff --git a/Bcfier.Revit/RevitWindow.xaml.cs b/Bcfier.Revit/RevitWindow.xaml.cs deleted file mode 100755 index 33a240d0..00000000 --- a/Bcfier.Revit/RevitWindow.xaml.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Input; - -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using Bcfier.Bcf.Bcf2; -using Bcfier.Revit.Data; -using Bcfier.Revit.Entry; -using System.ComponentModel; -using System.Threading.Tasks; -using Component = Bcfier.Bcf.Bcf2.Component; -using Point = Bcfier.Bcf.Bcf2.Point; -using Bcfier.Data.Utils; - -namespace Bcfier.Revit -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class RevitWindow : Window - { - private ExternalEvent ExtEvent; - private ExtEvntOpenView Handler; - private UIApplication uiapp; - - /// - /// Constructor - /// - /// - /// - /// - public RevitWindow(UIApplication _uiapp, ExternalEvent exEvent, ExtEvntOpenView handler) - { - InitializeComponent(); - - try - { - ExtEvent = exEvent; - Handler = handler; - uiapp = _uiapp; - } - catch (Exception ex1) - { - TaskDialog.Show("Error!", "exception: " + ex1); - } - } - - #region commands - /// - /// Raises the External Event to accomplish a transaction in a modeless window - /// http://help.autodesk.com/view/RVT/2014/ENU/?guid=GUID-0A0D656E-5C44-49E8-A891-6C29F88E35C0 - /// http://matteocominetti.com/starting-a-transaction-from-an-external-application-running-outside-of-api-context-is-not-allowed/ - /// - /// - /// - private void OnOpenView(object sender, ExecutedRoutedEventArgs e) - { - try - { - if (Bcfier.SelectedBcf() == null) - return; - var view = e.Parameter as ViewPoint; - if (view == null) - return; - UIDocument uidoc = uiapp.ActiveUIDocument; - - if (uidoc.ActiveView.ViewType == ViewType.Schedule) - { - MessageBox.Show("BCFier can't take snapshots of schedules.", - "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning); - return; - } - - if (uidoc.ActiveView.ViewType == ViewType.ThreeD) - { - var view3D = (View3D)uidoc.ActiveView; - if (view3D.IsPerspective) - { - MessageBox.Show("This operation is not allowed in a Perspective View.\nPlease close the current window(s) and retry.", - "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning); - return; - } - - } - Handler.v = view.VisInfo; - ExtEvent.Raise(); - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error opening a View!", "exception: " + ex1); - } - } - /// - /// Same as in the windows app, but here we generate a VisInfo that is attached to the view - /// - /// - /// - private void OnAddView(object sender, ExecutedRoutedEventArgs e) - { - try - { - - if (Bcfier.SelectedBcf() == null) - return; - var issue = e.Parameter as Markup; - if (issue == null) - { - MessageBox.Show("No Issue selected", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return; - } - - var dialog = new AddViewRevit(issue, Bcfier.SelectedBcf().TempPath, uiapp.ActiveUIDocument.Document); - dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; - dialog.ShowDialog(); - if (dialog.DialogResult.HasValue && dialog.DialogResult.Value) - { - //generate and set the VisInfo - issue.Viewpoints.Last().VisInfo = RevitView.GenerateViewpoint(uiapp.ActiveUIDocument); - - //get filename - UIDocument uidoc = uiapp.ActiveUIDocument; - - if (uidoc.Document.Title != null) - issue.Header[0].Filename = uidoc.Document.Title; - else - issue.Header[0].Filename = "Unknown"; - - Bcfier.SelectedBcf().HasBeenSaved = false; - } - - } - catch (System.Exception ex1) - { - TaskDialog.Show("Error adding a View!", "exception: " + ex1); - } - } - #endregion - - #region private methods - - /// - /// passing event to the user control - /// - /// - /// - private void Window_Closing(object sender, CancelEventArgs e) - { - e.Cancel = Bcfier.onClosing(e); - } - #endregion - - //stats - private void RevitWindow_OnLoaded(object sender, RoutedEventArgs e) - { - Task.Run(() => - { - StatHat.Post.EzCounter(@"hello@teocomi.com", "BCFierRevitStart", 1); - }); - } - - } -} \ No newline at end of file diff --git a/Bcfier.Revit/packages.config b/Bcfier.Revit/packages.config deleted file mode 100644 index a6ed660e..00000000 --- a/Bcfier.Revit/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Bcfier.Win/App.config b/Bcfier.Win/App.config deleted file mode 100644 index d1428ad7..00000000 --- a/Bcfier.Win/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Bcfier.Win/App.xaml b/Bcfier.Win/App.xaml deleted file mode 100644 index 4c7bed61..00000000 --- a/Bcfier.Win/App.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/Bcfier.Win/App.xaml.cs b/Bcfier.Win/App.xaml.cs deleted file mode 100644 index ccf99dcb..00000000 --- a/Bcfier.Win/App.xaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Windows; - -namespace Bcfier.Win -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - } -} diff --git a/Bcfier.Win/Assets/icon.ico b/Bcfier.Win/Assets/icon.ico deleted file mode 100644 index 6a2bf0a3..00000000 Binary files a/Bcfier.Win/Assets/icon.ico and /dev/null differ diff --git a/Bcfier.Win/Bcfier.Win.csproj b/Bcfier.Win/Bcfier.Win.csproj deleted file mode 100644 index 5946294c..00000000 --- a/Bcfier.Win/Bcfier.Win.csproj +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Debug - AnyCPU - {3C03085B-63AD-4890-AC2C-A4DE31AF1A6B} - WinExe - Properties - Bcfier.Win - Bcfier.Win - v4.5 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - Assets\icon.ico - - - true - bin\ManualObfuscation\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - false - - - true - bin\Debug-2015\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2016\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2017\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2015\ - - - bin\Release-2016\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2017\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2018\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2018\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2019\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2019\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2021\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2021\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release2020\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2020\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - - - - - - - - - 4.0 - - - - - - - - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Properties\AssemblyVersionInfo.cs - - - App.xaml - Code - - - MainWindow.xaml - Code - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 4.5 - true - - - - - {503ce2c1-09d7-4f15-bb42-86196ee01ed4} - Bcfier - - - - - - - - \ No newline at end of file diff --git a/Bcfier.Win/MainWindow.xaml b/Bcfier.Win/MainWindow.xaml deleted file mode 100755 index 8f22a531..00000000 --- a/Bcfier.Win/MainWindow.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - diff --git a/Bcfier.Win/MainWindow.xaml.cs b/Bcfier.Win/MainWindow.xaml.cs deleted file mode 100755 index 9509d00f..00000000 --- a/Bcfier.Win/MainWindow.xaml.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.IO; -using System.Windows; -using System.ComponentModel; -using System.Threading.Tasks; -using System.Windows.Input; -using System.Windows.Threading; -using Bcfier.Bcf.Bcf2; -using Bcfier.UserControls; - - -namespace Bcfier.Win -{ - - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window - { - public MainWindow() - { - InitializeComponent(); - - string[] args = Environment.GetCommandLineArgs(); - if (args.Length > 1 && File.Exists(args[1])) - { - Bcfier.Dispatcher.BeginInvoke(DispatcherPriority.Background, - new Action(() => Bcfier.BcfFileClicked(args[1]))); - } - } - - /// - /// passing event to the user control - /// - /// - /// - private void Window_Closing(object sender, CancelEventArgs e) - { - e.Cancel = Bcfier.onClosing(e); - } - - #region commands - - - private void OnAddView(object sender, ExecutedRoutedEventArgs e) - { - try - { - - if (Bcfier.SelectedBcf() == null) - return; - var issue = e.Parameter as Markup; - if (issue == null) - { - MessageBox.Show("No Issue selected", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return; - } - - var addView = new AddView(issue, Bcfier.SelectedBcf().TempPath); - var win = new Window - { - Content = addView, - Title = "Add View", - SizeToContent = SizeToContent.WidthAndHeight, - WindowStartupLocation = WindowStartupLocation.CenterScreen - }; - win.ShowDialog(); - if (win.DialogResult.HasValue && win.DialogResult.Value) - Bcfier.SelectedBcf().HasBeenSaved = false; - - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - #endregion - - private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) - { - Task.Run(() => - { - StatHat.Post.EzCounter(@"hello@teocomi.com", "BCFierWinStart", 1); - }); - } - } -} \ No newline at end of file diff --git a/Bcfier.Win/Properties/AssemblyInfo.cs b/Bcfier.Win/Properties/AssemblyInfo.cs deleted file mode 100755 index e15bbc5d..00000000 --- a/Bcfier.Win/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bcfier.Win")] -[assembly: AssemblyDescription("Bcfier.Win")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("teocomi")] -[assembly: AssemblyProduct("Bcfier.Win")] -[assembly: AssemblyCopyright("Copyright © teocomi 2017")] -[assembly: AssemblyTrademark("teocomi")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - -[assembly: GuidAttribute("9FC6BA85-A348-40B4-97C4-6699DA912C21")] diff --git a/Bcfier.Win/Properties/Resources.Designer.cs b/Bcfier.Win/Properties/Resources.Designer.cs deleted file mode 100644 index 66565415..00000000 --- a/Bcfier.Win/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Win.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bcfier.Win.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Bcfier.Win/Properties/Resources.resx b/Bcfier.Win/Properties/Resources.resx deleted file mode 100644 index af7dbebb..00000000 --- a/Bcfier.Win/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bcfier.Win/Properties/Settings.Designer.cs b/Bcfier.Win/Properties/Settings.Designer.cs deleted file mode 100644 index 16a2a3bf..00000000 --- a/Bcfier.Win/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Win.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Bcfier.Win/Properties/Settings.settings b/Bcfier.Win/Properties/Settings.settings deleted file mode 100644 index 033d7a5e..00000000 --- a/Bcfier.Win/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier.Win/packages.config b/Bcfier.Win/packages.config deleted file mode 100644 index a6ed660e..00000000 --- a/Bcfier.Win/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Bcfier.XbimXplorer/AddViewXbim.xaml b/Bcfier.XbimXplorer/AddViewXbim.xaml deleted file mode 100644 index b9e910ba..00000000 --- a/Bcfier.XbimXplorer/AddViewXbim.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/Bcfier.XbimXplorer/AddViewXbim.xaml.cs b/Bcfier.XbimXplorer/AddViewXbim.xaml.cs deleted file mode 100644 index 0b4b8d68..00000000 --- a/Bcfier.XbimXplorer/AddViewXbim.xaml.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.IO; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using Bcfier.Bcf.Bcf2; -using log4net; -using Xbim.Presentation; - -namespace Bcfier.XbimXplorer -{ - /// - /// Interaction logic for AddViewRevit.xaml - /// - public partial class AddViewXbim - { - private static readonly ILog Log = LogManager.GetLogger(nameof(AddViewXbim)); - private readonly DrawingControl3D _control; - - public AddViewXbim(Markup issue, string bcfTempFolder, DrawingControl3D control) - { - try - { - InitializeComponent(); - AddViewControl.Issue = issue; - AddViewControl.TempFolder = bcfTempFolder; - _control = control; - - AddViewControl.TextBlockInfo.Text = - "3D/2D information of the current view will be included in the viewpoint"; - - GetRevitSnapshot(); - } - catch (Exception ex) - { - MessageBox.Show("Error!", "exception: " + ex); - } - } - - private static RenderTargetBitmap Get3DVisual(FrameworkElement element) - { - var width = element.ActualWidth; - - var height = element.ActualHeight; - var bmpCopied = new RenderTargetBitmap((int) Math.Round(width), (int) Math.Round(height), 96, 96, - PixelFormats.Default); - var dv = new DrawingVisual(); - using (var dc = dv.RenderOpen()) - { - var vb = new VisualBrush(element); - dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new Size(width, height))); - } - bmpCopied.Render(dv); - return bmpCopied; - } - - private bool SaveControlPng(FrameworkElement control, string outFile) - { - try - { - var renderTargetBitmap = Get3DVisual(control); - - var bitmapEncoder = new PngBitmapEncoder(); - bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap)); - - using (var stream = File.Create(outFile)) - { - bitmapEncoder.Save(stream); - stream.Seek(0, SeekOrigin.Begin); - } - } - catch (Exception ex) - { - Log.Error("Counld not create screenshot from model.", ex); - return false; - } - return true; - } - - private void GetRevitSnapshot() - { - try - { - var tempImg = Path.Combine(Path.GetTempPath(), "BCFier", Path.GetTempFileName() + ".png"); - - var success = SaveControlPng(_control, tempImg); - if (!success) - { - return; - } - AddViewControl.AddViewpoint(tempImg); - File.Delete(tempImg); - } - catch (Exception ex) - { - MessageBox.Show("Error!", "exception: " + ex); - } - } - } -} \ No newline at end of file diff --git a/Bcfier.XbimXplorer/App.config b/Bcfier.XbimXplorer/App.config deleted file mode 100644 index 88fa4027..00000000 --- a/Bcfier.XbimXplorer/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Bcfier.XbimXplorer/App.xaml b/Bcfier.XbimXplorer/App.xaml deleted file mode 100644 index a0390c16..00000000 --- a/Bcfier.XbimXplorer/App.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/Bcfier.XbimXplorer/App.xaml.cs b/Bcfier.XbimXplorer/App.xaml.cs deleted file mode 100644 index c2f35381..00000000 --- a/Bcfier.XbimXplorer/App.xaml.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Bcfier.XbimXplorer -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App - { - } -} diff --git a/Bcfier.XbimXplorer/Assets/icon.ico b/Bcfier.XbimXplorer/Assets/icon.ico deleted file mode 100644 index 6a2bf0a3..00000000 Binary files a/Bcfier.XbimXplorer/Assets/icon.ico and /dev/null differ diff --git a/Bcfier.XbimXplorer/Bcfier.XbimXplorer.csproj b/Bcfier.XbimXplorer/Bcfier.XbimXplorer.csproj deleted file mode 100644 index 633ff09a..00000000 --- a/Bcfier.XbimXplorer/Bcfier.XbimXplorer.csproj +++ /dev/null @@ -1,299 +0,0 @@ - - - - - Debug - AnyCPU - {4CD7CA76-A40E-4DF4-831D-36B64818CC69} - WinExe - Properties - Bcfier.XbimXplorer - Bcfier.XbimXplorer - v4.5.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\Release-2018\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - true - - - true - bin\Debug-2018\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - true - - - true - bin\Debug-2019\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - true - - - bin\Release-2019\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - true - - - true - bin\Debug-2021\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\Release-2021\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\Release2020\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - true - - - true - bin\Debug-2020\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - true - - - - ..\packages\ManagedEsent.1.9.4\lib\net40\Esent.Interop.dll - True - - - ..\packages\HelixToolkit.2015.1.715\lib\portable-net4+sl4+wp71+win8\HelixToolkit.dll - True - - - ..\packages\HelixToolkit.Wpf.2015.1.715\lib\net45\HelixToolkit.Wpf.dll - True - - - ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll - True - - - ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll - True - - - ..\packages\PropertyTools.Wpf.2015.1.66\lib\net45\PropertyTools.dll - True - - - ..\packages\PropertyTools.Wpf.2015.1.66\lib\net45\PropertyTools.Wpf.dll - True - - - - - - - - - - - 4.0 - - - - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.CobieExpress.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Common.dll - True - - - ..\packages\Xbim.Geometry.4.0.11\lib\net40\Xbim.Geometry.Engine.Interop.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Ifc.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Ifc.Extensions.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Ifc2x3.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Ifc2x3.IO.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Ifc4.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.IO.dll - True - - - ..\packages\Xbim.Geometry.4.0.11\lib\net40\Xbim.ModelGeometry.Scene.dll - True - - - ..\packages\Xbim.WindowsUI.4.0.11\lib\net45\Xbim.Presentation.dll - True - - - ..\packages\Xbim.Essentials.4.0.7\lib\net40\Xbim.Tessellator.dll - True - - - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Properties\AssemblyVersionInfo.cs - - - AddViewXbim.xaml - - - App.xaml - Code - - - MainWindow.xaml - Code - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - - {503ce2c1-09d7-4f15-bb42-86196ee01ed4} - Bcfier - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Bcfier.XbimXplorer/Bcfier.XbimXplorer.plugin.nuspec b/Bcfier.XbimXplorer/Bcfier.XbimXplorer.plugin.nuspec deleted file mode 100644 index 9adbd9c3..00000000 --- a/Bcfier.XbimXplorer/Bcfier.XbimXplorer.plugin.nuspec +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Bcfier.XbimXplorer - 4.0.1-V0001 - Bcfier.XbimXplorer - Claudio Benghi, Matteo Cominetti - Claudio Benghi, Matteo Cominetti - https://raw.githubusercontent.com/CBenghi/BCFier/blob/master/LICENSE - http://bcfier.com/ - https://raw.githubusercontent.com/teocomi/BCFier/master/Bcfier/Assets/BCFierIcon64x64.png - true - Integration of Matteo Cominetti's BCFier editor of BuildingSmart's BCF. - . - en-GB - - BCF, Building Collaboration Format, BuildingSmart, XplorerPlugin - - - - - - - - - - - diff --git a/Bcfier.XbimXplorer/MainWindow.xaml b/Bcfier.XbimXplorer/MainWindow.xaml deleted file mode 100644 index 63ce79a1..00000000 --- a/Bcfier.XbimXplorer/MainWindow.xaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - diff --git a/Bcfier.XbimXplorer/MainWindow.xaml.cs b/Bcfier.XbimXplorer/MainWindow.xaml.cs deleted file mode 100644 index c6248105..00000000 --- a/Bcfier.XbimXplorer/MainWindow.xaml.cs +++ /dev/null @@ -1,286 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media.Media3D; -using Bcfier.Bcf.Bcf2; -using Xbim.Common.Geometry; -using Xbim.Presentation; -using Xbim.Presentation.XplorerPluginSystem; -using PerspectiveCamera = Bcfier.Bcf.Bcf2.PerspectiveCamera; - -namespace Bcfier.XbimXplorer -{ - // todo: implement IXbimXplorerPluginMessageReceiver interface - /// - /// Interaction logic for MainWindow.xaml - /// - [XplorerUiElement(PluginWindowUiContainerEnum.LayoutDoc, PluginWindowActivation.OnMenu, "BCFier BCF Editor")] - public partial class MainWindow : IXbimXplorerPluginWindow //, IXbimXplorerPluginMessageReceiver - { - public MainWindow() - { - InitializeComponent(); - WindowTitle = "BCFier BCF Editor"; - } - - // -------------------------- - // plugin system related code - // - - private IXbimXplorerPluginMasterWindow _xpWindow; - - public void BindUi(IXbimXplorerPluginMasterWindow mainWindow) - { - _xpWindow = mainWindow; - } - - public string WindowTitle { get; } - - private void OnOpenView(object sender, ExecutedRoutedEventArgs e) - { - - if (Bcfier.SelectedBcf() == null) - return; - var view = e?.Parameter as ViewPoint; - - if (view == null) - return; - var v = view.VisInfo; - - var position = new XbimPoint3D(); - var direction = new XbimPoint3D(); - var upDirection = new XbimPoint3D(); - - if (v.PerspectiveCamera != null) - { - // todo: this works internally, but we must ensure it's compatible with other bcf viewers - var pc = v.PerspectiveCamera; - position = new XbimPoint3D(pc.CameraViewPoint.X, pc.CameraViewPoint.Y, pc.CameraViewPoint.Z); - direction = new XbimPoint3D(pc.CameraDirection.X, pc.CameraDirection.Y, pc.CameraDirection.Z); - upDirection = new XbimPoint3D(pc.CameraUpVector.X, pc.CameraUpVector.Y, pc.CameraUpVector.Z); - - _xpWindow.DrawingControl.Viewport.Orthographic = false; - var pCam = _xpWindow.DrawingControl.Viewport.Camera as System.Windows.Media.Media3D.PerspectiveCamera; - if (pCam != null) - pCam.FieldOfView = pc.FieldOfView; - } - else if (v.OrthogonalCamera != null) - { - // todo: this works internally, but we must ensure it's compatible with other bcf viewers - var pc = v.OrthogonalCamera; - _xpWindow.DrawingControl.Viewport.Orthographic = true; - position = new XbimPoint3D(pc.CameraViewPoint.X, pc.CameraViewPoint.Y, pc.CameraViewPoint.Z); - direction = new XbimPoint3D(pc.CameraDirection.X, pc.CameraDirection.Y, pc.CameraDirection.Z); - upDirection = new XbimPoint3D(pc.CameraUpVector.X, pc.CameraUpVector.Y, pc.CameraUpVector.Z); - - var pCam = _xpWindow.DrawingControl.Viewport.Camera as OrthographicCamera; - if (pCam != null) - pCam.Width = pc.ViewToWorldScale; - } - var directionV = new XbimVector3D(direction.X, direction.Y, direction.Z); - var upDirectionV = new XbimVector3D(upDirection.X, upDirection.Y, upDirection.Z); - - var pos = new Point3D(position.X, position.Y, position.Z); - var dir = new Vector3D(directionV.X, directionV.Y, directionV.Z); - var upDir = new Vector3D(upDirectionV.X, upDirectionV.Y, upDirectionV.Z); - _xpWindow.DrawingControl.Viewport.SetView(pos, dir, upDir, 500); - - if (v.ClippingPlanes != null && v.ClippingPlanes.Any()) { - var curP = v.ClippingPlanes[0]; - _xpWindow.DrawingControl.SetCutPlane( - curP.Location.X, curP.Location.Y, curP.Location.Z, - curP.Direction.X, curP.Direction.Y, curP.Direction.Z - ); - } - else - { - _xpWindow.DrawingControl.ClearCutPlane(); - } - - // todo: components list to be implemented - } - - /// - /// Same as in the windows app, but here we generate a VisInfo that is attached to the view - /// - /// - /// - private void OnAddView(object sender, ExecutedRoutedEventArgs e) - { - try - { - if (Bcfier.SelectedBcf() == null) - return; - var issue = e.Parameter as Markup; - if (issue == null) - { - MessageBox.Show("No Issue selected", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return; - } - - var dialog = new AddViewXbim(issue, Bcfier.SelectedBcf().TempPath, _xpWindow.DrawingControl) - { - WindowStartupLocation = WindowStartupLocation.CenterScreen - }; - dialog.ShowDialog(); - if (!dialog.DialogResult.HasValue || !dialog.DialogResult.Value) - return; - - //generate and set the VisInfo - issue.Viewpoints.Last().VisInfo = GenerateViewpoint(_xpWindow.DrawingControl); - - //get filename - var fileName = _xpWindow.GetOpenedModelFileName(); - if (string.IsNullOrEmpty(fileName)) - fileName = "Unknown"; - issue.Header[0].Filename = fileName; - Bcfier.SelectedBcf().HasBeenSaved = false; - } - catch (Exception ex) - { - MessageBox.Show("Error adding a View!", "exception: " + ex); - } - } - - private static VisualizationInfo GenerateViewpoint(DrawingControl3D control3D) - { - try - { - var v = new VisualizationInfo(); - // it is a orthogonal view - if (control3D.Viewport.Orthographic) - { - // ReSharper disable once RedundantNameQualifier - var cam = control3D.Viewport.Camera as System.Windows.Media.Media3D.OrthographicCamera; - - if (cam != null) - v.OrthogonalCamera = new OrthogonalCamera - { - // todo: this works internally, but we must ensure it's compatible with other bcf viewers - CameraViewPoint = - { - X = cam.Position.X, - Y = cam.Position.Y, - Z = cam.Position.Z - }, - CameraUpVector = - { - X = cam.UpDirection.X, - Y = cam.UpDirection.Y, - Z = cam.UpDirection.Z - }, - CameraDirection = - { - X = cam.LookDirection.X, - Y = cam.LookDirection.Y, - Z = cam.LookDirection.Z - }, - ViewToWorldScale = cam.Width - }; - } - // it is a perspective view - else - { - // todo: this works internally, but we must ensure it's compatible with other bcf viewers - var cam = control3D.Viewport.Camera as System.Windows.Media.Media3D.PerspectiveCamera; - if (cam != null) - v.PerspectiveCamera = new PerspectiveCamera() - { - CameraViewPoint = - { - X = cam.Position.X, - Y = cam.Position.Y, - Z = cam.Position.Z - }, - CameraUpVector = - { - X = cam.UpDirection.X, - Y = cam.UpDirection.Y, - Z = cam.UpDirection.Z - }, - CameraDirection = - { - X = cam.LookDirection.X, - Y = cam.LookDirection.Y, - Z = cam.LookDirection.Z - }, - FieldOfView = cam.FieldOfView - }; - } - - /* todo components list to be implemented - - //COMPONENTS PART - var versionName = "XbimXplorer BCFIer Plugin"; - v.Components = new List(); - - var visibleElems = new FilteredElementCollector(doc, doc.ActiveView.Id) - .WhereElementIsNotElementType() - .WhereElementIsViewIndependent() - .ToElementIds(); - var hiddenElems = new FilteredElementCollector(doc) - .WhereElementIsNotElementType() - .WhereElementIsViewIndependent() - .Where(x => x.IsHidden(doc.ActiveView) - || - !doc.ActiveView.IsElementVisibleInTemporaryViewMode( - TemporaryViewMode.TemporaryHideIsolate, x.Id)).ToList(); - //would need to check how much this is affecting performance - - var selectedElems = uidoc.Selection.GetElementIds(); - - //include only hidden elements and selected in the BCF - if (visibleElems.Count() > hiddenElems.Count()) - { - foreach (var elem in hiddenElems) - { - v.Components.Add(new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, elem.Id)), - Visible = false, - Selected = false, - AuthoringToolId = elem.Id.IntegerValue.ToString() - }); - } - foreach (var elem in selectedElems) - { - v.Components.Add(new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, elem)), - Visible = true, - Selected = true, - AuthoringToolId = elem.IntegerValue.ToString() - }); - } - } - //include only visible elements - //all the others are hidden - else - { - foreach (var elem in visibleElems) - { - v.Components.Add(new Component - { - OriginatingSystem = versionName, - IfcGuid = IfcGuid.ToIfcGuid(ExportUtils.GetExportId(doc, elem)), - Visible = true, - Selected = selectedElems.Contains(elem), - AuthoringToolId = elem.IntegerValue.ToString() - }); - } - } - */ - return v; - - } - catch (Exception ex) - { - MessageBox.Show("Error generating viewpoint", "exception: " + ex); - } - return null; - } - } -} \ No newline at end of file diff --git a/Bcfier.XbimXplorer/MakeNugetInstaller.bat b/Bcfier.XbimXplorer/MakeNugetInstaller.bat deleted file mode 100644 index 1ddb15ad..00000000 --- a/Bcfier.XbimXplorer/MakeNugetInstaller.bat +++ /dev/null @@ -1,3 +0,0 @@ -md "bin\Packages" -"C:\Program Files (x86)\NuGet\nuget.exe" pack "Bcfier.XbimXplorer.plugin.nuspec" -o bin\Packages -@pause diff --git a/Bcfier.XbimXplorer/Properties/AssemblyInfo.cs b/Bcfier.XbimXplorer/Properties/AssemblyInfo.cs deleted file mode 100644 index dba9eee7..00000000 --- a/Bcfier.XbimXplorer/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bcfier.XbimXplorer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Bcfier.XbimXplorer")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - diff --git a/Bcfier.XbimXplorer/Properties/Resources.Designer.cs b/Bcfier.XbimXplorer/Properties/Resources.Designer.cs deleted file mode 100644 index 6034ee4e..00000000 --- a/Bcfier.XbimXplorer/Properties/Resources.Designer.cs +++ /dev/null @@ -1,71 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.XbimXplorer.Properties -{ - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bcfier.XbimXplorer.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { - return resourceCulture; - } - set - { - resourceCulture = value; - } - } - } -} diff --git a/Bcfier.XbimXplorer/Properties/Resources.resx b/Bcfier.XbimXplorer/Properties/Resources.resx deleted file mode 100644 index af7dbebb..00000000 --- a/Bcfier.XbimXplorer/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bcfier.XbimXplorer/Properties/Settings.Designer.cs b/Bcfier.XbimXplorer/Properties/Settings.Designer.cs deleted file mode 100644 index 9418c58e..00000000 --- a/Bcfier.XbimXplorer/Properties/Settings.Designer.cs +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.XbimXplorer.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } - } - } -} diff --git a/Bcfier.XbimXplorer/Properties/Settings.settings b/Bcfier.XbimXplorer/Properties/Settings.settings deleted file mode 100644 index 033d7a5e..00000000 --- a/Bcfier.XbimXplorer/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier.XbimXplorer/packages.config b/Bcfier.XbimXplorer/packages.config deleted file mode 100644 index 192c7158..00000000 --- a/Bcfier.XbimXplorer/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Api/GitHubAsset.cs b/Bcfier/Api/GitHubAsset.cs deleted file mode 100644 index b86e07a5..00000000 --- a/Bcfier/Api/GitHubAsset.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bcfier.Api -{ - public class GitHubAsset - { - public string url { get; set; } - public int id { get; set; } - public string name { get; set; } - public object label { get; set; } - public GitHubAuthor uploader { get; set; } - public string content_type { get; set; } - public string state { get; set; } - public int size { get; set; } - public int download_count { get; set; } - public string created_at { get; set; } - public string updated_at { get; set; } - public string browser_download_url { get; set; } -} - } - diff --git a/Bcfier/Api/GitHubAuthor.cs b/Bcfier/Api/GitHubAuthor.cs deleted file mode 100644 index 7aeb2ce3..00000000 --- a/Bcfier/Api/GitHubAuthor.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bcfier.Api -{ - public class GitHubAuthor - { - public string login { get; set; } - public int id { get; set; } - public string avatar_url { get; set; } - public string gravatar_id { get; set; } - public string url { get; set; } - public string html_url { get; set; } - public string followers_url { get; set; } - public string following_url { get; set; } - public string gists_url { get; set; } - public string starred_url { get; set; } - public string subscriptions_url { get; set; } - public string organizations_url { get; set; } - public string repos_url { get; set; } - public string events_url { get; set; } - public string received_events_url { get; set; } - public string type { get; set; } - public bool site_admin { get; set; } - } -} diff --git a/Bcfier/Api/GitHubRelease.cs b/Bcfier/Api/GitHubRelease.cs deleted file mode 100644 index 97d55eab..00000000 --- a/Bcfier/Api/GitHubRelease.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bcfier.Api -{ - public class GitHubRelease - { - public string url { get; set; } - public string assets_url { get; set; } - public string upload_url { get; set; } - public string html_url { get; set; } - public int id { get; set; } - public string tag_name { get; set; } - public string target_commitish { get; set; } - public string name { get; set; } - public bool draft { get; set; } - public GitHubAuthor author { get; set; } - public bool prerelease { get; set; } - public DateTime created_at { get; set; } - public DateTime published_at { get; set; } - public List assets { get; set; } - public string tarball_url { get; set; } - public string zipball_url { get; set; } - public string body { get; set; } - } -} \ No newline at end of file diff --git a/Bcfier/Api/GitHubRest.cs b/Bcfier/Api/GitHubRest.cs deleted file mode 100755 index 958a8093..00000000 --- a/Bcfier/Api/GitHubRest.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using RestSharp; -using DataFormat = RestSharp.DataFormat; - -namespace Bcfier.Api -{ - public static class GitHubRest - { - internal static RestClient Client - { - get { return new RestClient(@"https://api.github.com/"); } - } - - internal static async Task> GetReleases(CancellationTokenSource cancel) - { - if (cancel.IsCancellationRequested) - return null; - - - var request = new RestRequest("repos/teocomi/bcfier/releases", Method.GET); - request.AddHeader("Content-Type", "application/json"); - request.RequestFormat = DataFormat.Json; - request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; }; - - var response = await DoTaskAsync>(request, cancel); - - return cancel.IsCancellationRequested || !CheckResponse(response, HttpStatusCode.OK) ? null : response.Data; - } - - internal static GitHubRelease GetLatestRelease() - { - - var request = new RestRequest("repos/teocomi/bcfier/releases/latest", Method.GET); - request.AddHeader("Content-Type", "application/json"); - request.RequestFormat = DataFormat.Json; - - var response = Client.Execute (request); - //if cancellation oending or invalid reponse return null, otherwise the data - return !CheckResponse(response, HttpStatusCode.OK) ? null : response.Data; - } - - private static async Task> DoTaskAsync(RestRequest request, CancellationTokenSource cancel) where T : class - { - IRestResponse response = null; - try - { - if (cancel != null) - response = await Client.ExecuteTaskAsync(request, cancel.Token); - } - catch (OperationCanceledException ex) - { - var gg = ex.Data; - return null; - } - return response; - } - - private static bool CheckResponse(IRestResponse response, HttpStatusCode expectedCode) - { - try - { - if (null == response || response.StatusCode != expectedCode) - return false; - } - catch (Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return true; - } - - - } -} diff --git a/Bcfier/Api/StatHat.cs b/Bcfier/Api/StatHat.cs deleted file mode 100755 index 53364888..00000000 --- a/Bcfier/Api/StatHat.cs +++ /dev/null @@ -1,358 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; - -namespace StatHat -{ - // Delegates - public delegate void ReplyDelegate(string reply); - - public static class Post - { - - // =================== - // How to use StatHat: - // =================== - // - // 1. Add StatHat.cs to your .NET project. - // 2. Call its functions! - // - // ----------------------------------------------------------------------------------- - // - // A simple example of posting a Counter: - // - // StatHat.Post.Counter("FERF34fREF3443432","23FSDfEFWFEF22323", 9.95); - // - // ----------------------------------------------------------------------------------- - // - // A simple example of posting a Value: - // - // StatHat.Post.Value("FERF34fREF3443432","23FSDfEFWFEF22323", 512.2); - // - // ----------------------------------------------------------------------------------- - // - // A simple example of posting a counter with our EZ API - this registers the stat automatically - // if it doesn't exist (and registers you for the site if you don't have a membership): - // - // StatHat.Post.EzCounter("you@example.com","dollars earned", 9.95); - // - // ----------------------------------------------------------------------------------- - // - // If you care to read what the server is replying to your call (for error handling, curiosity, etc.) - // you can pass a delegate function expecting a string for callback. Like so: - // - // - // // Here's some function I want StatHat to call with the reply: - // // --------------------------------------------------- - // void PrintStatHatReply(string reply) { Console.WriteLine(reply); } - // - // // Make a delegate out of it. - // // ----------------------------- - // StatHat.ReplyDelegate myDelegate = new StatHat.ReplyDelegate(PrintStatHatReply); - // - // // Pass that delegate as a parameter: - // // ---------------------------------- - // StatHat.Post.Counter("FERF34fREF3443432","23FSDfEFWFEF22323", 1.0, myDelegate); - // - // - - private const string BaseUrl = "http://api.stathat.com"; - - /// - /// Posts a counter increment to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number to increment - public static void Counter(string key, string ukey, float count) - { - Dictionary p = new Dictionary(); - p.Add("key", key); - p.Add("ukey", ukey); - p.Add("count", count.ToString()); - new FormPoster(Post.BaseUrl, "/c", p); - } - - - /// - /// Posts a counter increment to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number to increment - public static void Counter(string key, string ukey, int count) - { - Post.Counter(key, ukey, (float)count); - - } - /// - /// Posts a value to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number - public static void Value(string key, string ukey, float value) - { - Dictionary p = new Dictionary(); - p.Add("key", key); - p.Add("ukey", ukey); - p.Add("value", value.ToString()); - new FormPoster(Post.BaseUrl, "/v", p); - } - /// - /// Posts a value to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number - public static void Value(string key, string ukey, int value) - { - Post.Value(key, ukey, (float)value); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number to increment - public static void EzCounter(string ezkey, string stat, float count) - { - Dictionary p = new Dictionary(); - p.Add("ezkey", ezkey); - p.Add("stat", stat); - p.Add("count", count.ToString()); - new FormPoster(Post.BaseUrl, "/ez", p); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number to increment - public static void EzCounter(string ezkey, string stat, int count) - { - Post.EzCounter(ezkey, stat, (float)count); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number - public static void EzValue(string ezkey, string stat, float value) - { - Dictionary p = new Dictionary(); - p.Add("ezkey", ezkey); - p.Add("stat", stat); - p.Add("value", value.ToString()); - new FormPoster(Post.BaseUrl, "/ez", p); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number - public static void EzValue(string ezkey, string stat, int value) - { - Post.EzValue(ezkey, stat, (float)value); - } - - /// - /// Posts a counter increment to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number to increment - /// the function you'd like called with the reply from stathat's server - public static void Counter(string key, string ukey, float count, ReplyDelegate replyDelegate) - { - Dictionary p = new Dictionary(); - p.Add("key", key); - p.Add("ukey", ukey); - p.Add("count", count.ToString()); - new FormPoster(Post.BaseUrl, "/c", p, replyDelegate); - } - /// - /// Posts a counter increment to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number to increment - /// the function you'd like called with the reply from stathat's server - public static void Counter(string key, string ukey, int count, ReplyDelegate replyDelegate) - { - Post.Counter(key, ukey, (float)count, replyDelegate); - - } - /// - /// Posts a value to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number - /// the function you'd like called with the reply from stathat's server - public static void Value(string key, string ukey, float value, ReplyDelegate replyDelegate) - { - Dictionary p = new Dictionary(); - p.Add("key", key); - p.Add("ukey", ukey); - p.Add("value", value.ToString()); - new FormPoster(Post.BaseUrl, "/v", p, replyDelegate); - } - /// - /// Posts a value to stathat over HTTP - /// - /// the stat's posting key - /// your user key - /// the number - /// the function you'd like called with the reply from stathat's server - public static void Value(string key, string ukey, int value, ReplyDelegate replyDelegate) - { - Post.Value(key, ukey, (float)value, replyDelegate); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number to increment - /// the function you'd like called with the reply from stathat's server - public static void EzCounter(string ezkey, string stat, float count, ReplyDelegate replyDelegate) - { - Dictionary p = new Dictionary(); - p.Add("ezkey", ezkey); - p.Add("stat", stat); - p.Add("count", count.ToString()); - new FormPoster(Post.BaseUrl, "/ez", p, replyDelegate); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number to increment - /// the function you'd like called with the reply from stathat's server - public static void EzCounter(string ezkey, string stat, int count, ReplyDelegate replyDelegate) - { - Post.EzCounter(ezkey, stat, (float)count, replyDelegate); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number - /// the function you'd like called with the reply from stathat's server - public static void EzValue(string ezkey, string stat, float value, ReplyDelegate replyDelegate) - { - Dictionary p = new Dictionary(); - p.Add("ezkey", ezkey); - p.Add("stat", stat); - p.Add("value", value.ToString()); - new FormPoster(Post.BaseUrl, "/ez", p, replyDelegate); - } - - /// - /// Posts a counter increment to stathat over HTTP using ez API - the stat and/or you don't have to be pre-registered - /// - /// your ezkey (defaults to email address). If you already have a stathat account, use the one associated with it. - /// the name for your stat - /// the number - /// the function you'd like called with the reply from stathat's server - public static void EzValue(string ezkey, string stat, int value, ReplyDelegate replyDelegate) - { - Post.EzValue(ezkey, stat, (float)value, replyDelegate); - } - - private class FormPoster - { - // Members - HttpWebRequest Request; - Dictionary Parameters; - ReplyDelegate Reply; - string RelUrl; - string BaseUrl; - - - // Methods - public FormPoster(string base_url, string rel_url, Dictionary parameters, ReplyDelegate replyDelegate) - { - this.BaseUrl = base_url; - this.Parameters = parameters; - this.Reply = replyDelegate; - this.RelUrl = rel_url; - this.PostForm(); - } - public FormPoster(string base_url, string rel_url, Dictionary parameters) - { - this.BaseUrl = base_url; - this.Parameters = parameters; - this.Reply = new ReplyDelegate((rep) => { }); - this.RelUrl = rel_url; - this.PostForm(); - } - - private void PostForm() - { - this.Request = (HttpWebRequest)WebRequest.Create(this.BaseUrl + this.RelUrl); - Request.Method = "POST"; - Request.ContentType = "application/x-www-form-urlencoded"; - Request.BeginGetRequestStream(this.RequestCallback, Request); - } - private void RequestCallback(IAsyncResult asyncResult) - { - try - { - string postData = ""; - foreach (string key in this.Parameters.Keys) - { - postData += encodeUriComponent(key) + "=" + encodeUriComponent(this.Parameters[key]) + "&"; - } - Stream newStream = Request.EndGetRequestStream(asyncResult); - StreamWriter streamWriter = new StreamWriter(newStream); - streamWriter.Write(postData); - streamWriter.Close(); - this.Request.BeginGetResponse(this.ResponseCallback, this.Request); - } - catch (Exception e) - { - this.Reply(e.Message); - } - finally { } - } - - private string encodeUriComponent(string s) - { - string res = s.Replace("&", "%26"); - res = res.Replace(" ", "%20"); - return res; - } - - private void ResponseCallback(IAsyncResult asyncResult) - { - try - { - WebResponse response = this.Request.EndGetResponse(asyncResult); - Stream dataStream = response.GetResponseStream(); - StreamReader reader = new StreamReader(dataStream); - string result = reader.ReadToEnd(); - this.Reply(result); - } - catch (Exception e) - { - this.Reply(e.Message); - } - finally { } - } - } - } -} \ No newline at end of file diff --git a/Bcfier/App.config b/Bcfier/App.config deleted file mode 100644 index d1428ad7..00000000 --- a/Bcfier/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Bcfier/Assets/BCFierIcon16x16.png b/Bcfier/Assets/BCFierIcon16x16.png deleted file mode 100644 index 39e117ef..00000000 Binary files a/Bcfier/Assets/BCFierIcon16x16.png and /dev/null differ diff --git a/Bcfier/Assets/BCFierIcon32x32.png b/Bcfier/Assets/BCFierIcon32x32.png deleted file mode 100644 index 4b45eddb..00000000 Binary files a/Bcfier/Assets/BCFierIcon32x32.png and /dev/null differ diff --git a/Bcfier/Assets/BCFierIcon64x64.png b/Bcfier/Assets/BCFierIcon64x64.png deleted file mode 100644 index c4efa173..00000000 Binary files a/Bcfier/Assets/BCFierIcon64x64.png and /dev/null differ diff --git a/Bcfier/Assets/icon.ico b/Bcfier/Assets/icon.ico deleted file mode 100644 index 6a2bf0a3..00000000 Binary files a/Bcfier/Assets/icon.ico and /dev/null differ diff --git a/Bcfier/Bcf/Bcf2/Markup.cs b/Bcfier/Bcf/Bcf2/Markup.cs deleted file mode 100644 index 907ae844..00000000 --- a/Bcfier/Bcf/Bcf2/Markup.cs +++ /dev/null @@ -1,974 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using Bcfier.Data; -using System.Xml.Serialization; - -namespace Bcfier.Bcf.Bcf2 -{ - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] - public partial class Markup : INotifyPropertyChanged - { - - private List headerField; - - private Topic topicField; - - private ObservableCollection commentField; - - private ObservableCollection viewpointsField; - - - /// - [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - [System.Xml.Serialization.XmlArrayItemAttribute("File", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, - IsNullable = false)] - public List Header - { - get { return this.headerField; } - set { this.headerField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public Topic Topic - { - get { return this.topicField; } - set { this.topicField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Comment", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public ObservableCollection Comment - { - get { return this.commentField; } - set - { - this.commentField = value; - NotifyPropertyChanged("Comment"); - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Viewpoints", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public ObservableCollection Viewpoints - { - get { return this.viewpointsField; } - set - { - this.viewpointsField = value; - NotifyPropertyChanged("Viewpoints"); - - } - } - /// - /// Generates ViewCommentobjects from View and Comments Dynamically - /// Could be removed by implmenting a proper MVVM model - /// But this approach simplifies things a lot - /// - - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ObservableCollection ViewComments - { - get - { - var viewCommentsField = new ObservableCollection(); - foreach (var viewpoint in Viewpoints) - { - var vc = new ViewComment - { - Viewpoint = viewpoint, - Comments = new ObservableCollection(Comment.Where(x => x.Viewpoint != null && x.Viewpoint.Guid == viewpoint.Guid)) - }; - viewCommentsField.Add(vc); - } - var vcEmpty = new ViewComment - { - Comments = - new ObservableCollection(Comment.Where(x => !Viewpoints.Any(v => x.Viewpoint != null && v.Guid == x.Viewpoint.Guid))) - }; - viewCommentsField.Add(vcEmpty); - return viewCommentsField; - } - } - - ////this might need to change - //[System.Xml.Serialization.XmlIgnoreAttribute()] - //public string LastCommentStatus - //{ - // get - // { - // if (Comment == null || !Comment.Any()) - // return ""; - - // return Comment.LastOrDefault().Status; - // } - //} - ////this might need to change - //[System.Xml.Serialization.XmlIgnoreAttribute()] - //public string LastCommentVerbalStatus - //{ - // get - // { - // if (Comment == null || !Comment.Any()) - // return ""; - - // return Comment.LastOrDefault().VerbalStatus; - // } - //} - - //parameterless constructor needed - public Markup() - { - } - public Markup(DateTime created) - { - Topic = new Topic(); - - Comment = new ObservableCollection(); - Viewpoints = new ObservableCollection(); - RegisterEvents(); - Header = new List { new HeaderFile { Date = created, DateSpecified = true } }; - } - //when Views or comments change refresh the ViewComments - public void RegisterEvents() - { - if (Viewpoints != null) - Viewpoints.CollectionChanged += delegate (object sender, NotifyCollectionChangedEventArgs args) { NotifyPropertyChanged("ViewComments"); }; - if (Comment != null) - Comment.CollectionChanged += CommentOnCollectionChanged; - } - - private void CommentOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) - { - NotifyPropertyChanged("ViewComments"); - //NotifyPropertyChanged("LastCommentStatus"); - //NotifyPropertyChanged("LastCommentVerbalStatus"); - } - [field: NonSerialized] - public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String info) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(info)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class HeaderFile - { - - private string filenameField; - - private System.DateTime dateField; - - private bool dateFieldSpecified; - - private string referenceField; - - private string ifcProjectField; - - private string ifcSpatialStructureElementField; - - private bool isExternalField; - - public HeaderFile() - { - this.isExternalField = true; - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Filename - { - get { return this.filenameField; } - set { this.filenameField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime Date - { - get { return this.dateField; } - set { this.dateField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool DateSpecified - { - get { return this.dateFieldSpecified; } - set { this.dateFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Reference - { - get { return this.referenceField; } - set { this.referenceField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string IfcProject - { - get { return this.ifcProjectField; } - set { this.ifcProjectField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string IfcSpatialStructureElement - { - get { return this.ifcSpatialStructureElementField; } - set { this.ifcSpatialStructureElementField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool isExternal - { - get { return this.isExternalField; } - set { this.isExternalField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class ViewPoint : INotifyPropertyChanged - { - - private string viewpointField; - - private string snapshotField; - - private int indexField; - - private bool indexFieldSpecified; - - private string guidField; - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Viewpoint - { - get { return this.viewpointField; } - set { this.viewpointField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Snapshot - { - get { return this.snapshotField; } - set { this.snapshotField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public int Index - { - get { return this.indexField; } - set { this.indexField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool IndexSpecified - { - get { return this.indexFieldSpecified; } - set { this.indexFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - public ViewPoint() - { - } - public ViewPoint(bool isFirst) - { - Guid = System.Guid.NewGuid().ToString(); - if (isFirst) - { - Viewpoint = "viewpoint.bcfv"; - Snapshot = "snapshot.png"; - } - else - { - Viewpoint = Guid + ".bcfv"; - Snapshot = Guid + ".png"; - } - - } - - [field: NonSerialized] - public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String info) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(info)); - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Comment - { - - //private string verbalStatusField; - - //private string statusField; - - private System.DateTime dateField; - - private string authorField; - - private string comment1Field; - - //private CommentTopic topicField; - - private CommentViewpoint viewpointField; - - //private CommentReplyToComment replyToCommentField; - - private System.DateTime modifiedDateField; - - private bool modifiedDateFieldSpecified; - - private string modifiedAuthorField; - - private string guidField; - - public Comment() - { - //this.statusField = "Unknown"; - } - - // /// - // [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - // public string VerbalStatus - // { - // get { return this.verbalStatusField; } - // set { this.verbalStatusField = value; } - // } - - // /// - // [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - // public string Status - // { - // get { return this.statusField; } - // set { this.statusField = value; } - // } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime Date - { - get { return this.dateField; } - set { this.dateField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Author - { - get { return this.authorField; } - set { this.authorField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Comment", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Comment1 - { - get { return this.comment1Field; } - set { this.comment1Field = value; } - } - - // /// - // [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - // public CommentTopic Topic - // { - // get { return this.topicField; } - // set { this.topicField = value; } - // } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public CommentViewpoint Viewpoint - { - get { return this.viewpointField; } - set { this.viewpointField = value; } - } - - // /// - // [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - // public CommentReplyToComment ReplyToComment - // { - // get { return this.replyToCommentField; } - // set { this.replyToCommentField = value; } - // } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime ModifiedDate - { - get { return this.modifiedDateField; } - set { this.modifiedDateField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool ModifiedDateSpecified - { - get { return this.modifiedDateFieldSpecified; } - set { this.modifiedDateFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string ModifiedAuthor - { - get { return this.modifiedAuthorField; } - set { this.modifiedAuthorField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - } - - // /// - // [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - // [System.SerializableAttribute()] - // [System.Diagnostics.DebuggerStepThroughAttribute()] - // [System.ComponentModel.DesignerCategoryAttribute("code")] - // [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - // public partial class CommentTopic - // { - - // private string guidField; - - // /// - // [System.Xml.Serialization.XmlAttributeAttribute()] - // public string Guid - // { - // get { return this.guidField; } - // set { this.guidField = value; } - // } - // } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class CommentViewpoint - { - - private string guidField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - } - - // /// - // [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - // [System.SerializableAttribute()] - // [System.Diagnostics.DebuggerStepThroughAttribute()] - // [System.ComponentModel.DesignerCategoryAttribute("code")] - // [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - // public partial class CommentReplyToComment - // { - - // private string guidField; - - // /// - // [System.Xml.Serialization.XmlAttributeAttribute()] - // public string Guid - // { - // get { return this.guidField; } - // set { this.guidField = value; } - // } - // } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class BimSnippet - { - - private string referenceField; - - private string referenceSchemaField; - - private string snippetTypeField; - - private bool isExternalField; - - public BimSnippet() - { - this.isExternalField = false; - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Reference - { - get { return this.referenceField; } - set { this.referenceField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string ReferenceSchema - { - get { return this.referenceSchemaField; } - set { this.referenceSchemaField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SnippetType - { - get { return this.snippetTypeField; } - set { this.snippetTypeField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool isExternal - { - get { return this.isExternalField; } - set { this.isExternalField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Topic - { - - private string[] referenceLinkField; - - private string titleField; - - private string priorityField; - - private int indexField; - - private bool indexFieldSpecified; - - private string[] labelsField; - - private System.DateTime creationDateField; - - //private bool creationDateFieldSpecified; - - private string creationAuthorField; - - private System.DateTime modifiedDateField; - - private bool modifiedDateFieldSpecified; - - private string modifiedAuthorField; - - private System.DateTime dueDateField; - - private bool dueDateFieldSpecified; - - private string assignedToField; - - private string stageField; - - private string descriptionField; - - private BimSnippet bimSnippetField; - - private TopicDocumentReferences[] documentReferencesField; - - private TopicRelatedTopics[] relatedTopicsField; - - private string guidField; - - private string topicTypeField; - - private ObservableCollection topicTypesCollection; - - private string topicStatusField; - - private ObservableCollection topicStatusesCollection; - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string[] ReferenceLink - { - get { return this.referenceLinkField; } - set { this.referenceLinkField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Title - { - get { return this.titleField; } - set { this.titleField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Priority - { - get { return this.priorityField; } - set { this.priorityField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public int Index - { - get - { - return this.indexField; - } - set - { - this.indexField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool IndexSpecified - { - get - { - return this.indexFieldSpecified; - } - set - { - this.indexFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Labels", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string[] Labels - { - get { return this.labelsField; } - set { this.labelsField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime CreationDate - { - get { return this.creationDateField; } - set { this.creationDateField = value; } - } - - // /// - // [System.Xml.Serialization.XmlIgnoreAttribute()] - // public bool CreationDateSpecified - // { - // get { return this.creationDateFieldSpecified; } - // set { this.creationDateFieldSpecified = value; } - // } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string CreationAuthor - { - get { return this.creationAuthorField; } - set { this.creationAuthorField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime ModifiedDate - { - get { return this.modifiedDateField; } - set { this.modifiedDateField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool ModifiedDateSpecified - { - get { return this.modifiedDateFieldSpecified; } - set { this.modifiedDateFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string ModifiedAuthor - { - get { return this.modifiedAuthorField; } - set { this.modifiedAuthorField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public System.DateTime DueDate - { - get - { - return this.dueDateField; - } - set - { - this.dueDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool DueDateSpecified - { - get - { - return this.dueDateFieldSpecified; - } - set - { - this.dueDateFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string AssignedTo - { - get { return this.assignedToField; } - set { this.assignedToField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Stage - { - get - { - return this.stageField; - } - set - { - this.stageField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Description - { - get { return this.descriptionField; } - set { this.descriptionField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public BimSnippet BimSnippet - { - get { return this.bimSnippetField; } - set { this.bimSnippetField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("DocumentReferences", - Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public TopicDocumentReferences[] DocumentReferences - { - get { return this.documentReferencesField; } - set { this.documentReferencesField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("RelatedTopics", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public TopicRelatedTopics[] RelatedTopics - { - get { return this.relatedTopicsField; } - set { this.relatedTopicsField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string TopicType - { - get { return this.topicTypeField; } - set { this.topicTypeField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string TopicStatus - { - get { return this.topicStatusField; } - set { this.topicStatusField = value; } - } - - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ObservableCollection TopicTypesCollection - { - get { return topicTypesCollection; } - set { this.topicTypesCollection = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ObservableCollection TopicStatusesCollection - { - get { return topicStatusesCollection; } - set { this.topicStatusesCollection = value; } - } - - public Topic() - { - Guid = System.Guid.NewGuid().ToString(); - CreationDate = DateTime.Now; - ModifiedDate = CreationDate; - - TopicStatusesCollection = new ObservableCollection(); - TopicTypesCollection = new ObservableCollection(); - foreach (var status in Globals.AvailStatuses) - { - TopicStatusesCollection.Add(status); - } - foreach (var type in Globals.AvailTypes) - { - TopicTypesCollection.Add(type); - } - - - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class TopicDocumentReferences - { - - private string referencedDocumentField; - - private string descriptionField; - - private string guidField; - - private bool isExternalField; - - public TopicDocumentReferences() - { - this.isExternalField = false; - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string ReferencedDocument - { - get { return this.referencedDocumentField; } - set { this.referencedDocumentField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Description - { - get { return this.descriptionField; } - set { this.descriptionField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool isExternal - { - get { return this.isExternalField; } - set { this.isExternalField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class TopicRelatedTopics - { - - private string guidField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - } -} diff --git a/Bcfier/Bcf/Bcf2/Project.cs b/Bcfier/Bcf/Bcf2/Project.cs deleted file mode 100755 index 09c2ab3d..00000000 --- a/Bcfier/Bcf/Bcf2/Project.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Xml.Serialization; - -namespace Bcfier.Bcf.Bcf2 -{ - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] - public partial class ProjectExtension - { - - private Project projectField; - - private string extensionSchemaField; - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public Project Project - { - get { return this.projectField; } - set { this.projectField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, - DataType = "anyURI")] - public string ExtensionSchema - { - get { return this.extensionSchemaField; } - set { this.extensionSchemaField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Project - { - - private string nameField; - - private string projectIdField; - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string Name - { - get { return this.nameField; } - set { this.nameField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ProjectId - { - get { return this.projectIdField; } - set { this.projectIdField = value; } - } - } -} diff --git a/Bcfier/Bcf/Bcf2/Version.cs b/Bcfier/Bcf/Bcf2/Version.cs deleted file mode 100644 index d5b4d0ee..00000000 --- a/Bcfier/Bcf/Bcf2/Version.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Xml.Serialization; - -namespace Bcfier.Bcf.Bcf2 -{ - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] - public partial class Version - { - - private string detailedVersionField; - - private string versionIdField; - - /// - [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] - public string DetailedVersion - { - get { return this.detailedVersionField; } - set { this.detailedVersionField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string VersionId - { - get { return this.versionIdField; } - set { this.versionIdField = value; } - } - } -} \ No newline at end of file diff --git a/Bcfier/Bcf/Bcf2/ViewComment.cs b/Bcfier/Bcf/Bcf2/ViewComment.cs deleted file mode 100644 index 9a14facc..00000000 --- a/Bcfier/Bcf/Bcf2/ViewComment.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Bcfier.Bcf.Bcf2; - -namespace Bcfier.Bcf.Bcf2 -{ - /// - /// View Model that binds to the BcfReportPanel grouping comments and viewpoints - /// Not part of BCF - /// - public class ViewComment - { - public ViewPoint Viewpoint - { - get; set; - } - public ObservableCollection Comments { get; set; } - - } -} diff --git a/Bcfier/Bcf/Bcf2/ViewPointExtended.cs b/Bcfier/Bcf/Bcf2/ViewPointExtended.cs deleted file mode 100644 index 994c1ea1..00000000 --- a/Bcfier/Bcf/Bcf2/ViewPointExtended.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Bcfier.Bcf.Bcf2; - -namespace Bcfier.Bcf.Bcf2 -{ - //I store the deserialized VisualizationInfo here (inside the markup) so there is a 1 to 1 corrispondence - //betweeen the Markup/Viewpoints tag and the actual viewpoints - //and I don't need to add any new class - //could be improved by creating a proper Model View / View Model class - public partial class ViewPoint - { - private VisualizationInfo _visInfoField; - - [System.Xml.Serialization.XmlIgnoreAttribute()] - public VisualizationInfo VisInfo - { - get - { - return this._visInfoField; - } - set - { - this._visInfoField = value; - } - } - - private string _snapshotPath; - - //used for an easier binding in the UI - [System.Xml.Serialization.XmlIgnoreAttribute()] - public string SnapshotPath - { - get - { - return this._snapshotPath; - } - set - { - this._snapshotPath = value; - NotifyPropertyChanged("SnapshotPath"); - } - } - } -} diff --git a/Bcfier/Bcf/Bcf2/Visinfo.cs b/Bcfier/Bcf/Bcf2/Visinfo.cs deleted file mode 100644 index 49715a3d..00000000 --- a/Bcfier/Bcf/Bcf2/Visinfo.cs +++ /dev/null @@ -1,688 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Serialization; - -namespace Bcfier.Bcf.Bcf2 -{ - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] - public partial class VisualizationInfo - { - - private Components componentsField; - - private OrthogonalCamera orthogonalCameraField; - - private PerspectiveCamera perspectiveCameraField; - - //Not part of BCF schema, added to support 2D views - private SheetCamera sheetCameraField; - - private Line[] linesField; - - private ClippingPlane[] clippingPlanesField; - - private VisualizationInfoBitmap[] bitmapField; - - private string guidField; - - /// - public Components Components - { - get { return this.componentsField; } - set { this.componentsField = value; } - } - - /// - public OrthogonalCamera OrthogonalCamera - { - get { return this.orthogonalCameraField; } - set { this.orthogonalCameraField = value; } - } - - /// - public PerspectiveCamera PerspectiveCamera - { - get { return this.perspectiveCameraField; } - set { this.perspectiveCameraField = value; } - } - - - public SheetCamera SheetCamera - { - get { return this.sheetCameraField; } - set { this.sheetCameraField = value; } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] - public Line[] Lines - { - get { return this.linesField; } - set { this.linesField = value; } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] - public ClippingPlane[] ClippingPlanes - { - get { return this.clippingPlanesField; } - set { this.clippingPlanesField = value; } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Bitmap")] - public VisualizationInfoBitmap[] Bitmap - { - get - { - return this.bitmapField; - } - set - { - this.bitmapField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Guid - { - get { return this.guidField; } - set { this.guidField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Components - { - - private ViewSetupHints viewSetupHintsField; - - private Component[] selectionField; - - private ComponentVisibility visibilityField; - - private ComponentColoringColor[] coloringField; - - /// - public ViewSetupHints ViewSetupHints - { - get { return this.viewSetupHintsField; } - set { this.viewSetupHintsField = value; } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] - public Component[] Selection - { - get { return this.selectionField; } - set { this.selectionField = value; } - } - - /// - public ComponentVisibility Visibility - { - get { return this.visibilityField; } - set { this.visibilityField = value; } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Color", IsNullable = false)] - public ComponentColoringColor[] Coloring - { - get { return this.coloringField; } - set { this.coloringField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class ViewSetupHints - { - - private bool spacesVisibleField; - - private bool spacesVisibleFieldSpecified; - - private bool spaceBoundariesVisibleField; - - private bool spaceBoundariesVisibleFieldSpecified; - - private bool openingsVisibleField; - - private bool openingsVisibleFieldSpecified; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool SpacesVisible - { - get { return this.spacesVisibleField; } - set { this.spacesVisibleField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool SpacesVisibleSpecified - { - get { return this.spacesVisibleFieldSpecified; } - set { this.spacesVisibleFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool SpaceBoundariesVisible - { - get { return this.spaceBoundariesVisibleField; } - set { this.spaceBoundariesVisibleField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool SpaceBoundariesVisibleSpecified - { - get { return this.spaceBoundariesVisibleFieldSpecified; } - set { this.spaceBoundariesVisibleFieldSpecified = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool OpeningsVisible - { - get { return this.openingsVisibleField; } - set { this.openingsVisibleField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool OpeningsVisibleSpecified - { - get { return this.openingsVisibleFieldSpecified; } - set { this.openingsVisibleFieldSpecified = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class ClippingPlane - { - - private Point locationField; - - private Direction directionField; - - /// - public Point Location - { - get { return this.locationField; } - set { this.locationField = value; } - } - - /// - public Direction Direction - { - get { return this.directionField; } - set { this.directionField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Point - { - - private double xField; - - private double yField; - - private double zField; - - /// - public double X - { - get { return this.xField; } - set { this.xField = value; } - } - - /// - public double Y - { - get { return this.yField; } - set { this.yField = value; } - } - - /// - public double Z - { - get { return this.zField; } - set { this.zField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Direction - { - - private double xField; - - private double yField; - - private double zField; - - /// - public double X - { - get { return this.xField; } - set { this.xField = value; } - } - - /// - public double Y - { - get { return this.yField; } - set { this.yField = value; } - } - - /// - public double Z - { - get { return this.zField; } - set { this.zField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Line - { - - private Point startPointField; - - private Point endPointField; - - /// - public Point StartPoint - { - get { return this.startPointField; } - set { this.startPointField = value; } - } - - /// - public Point EndPoint - { - get { return this.endPointField; } - set { this.endPointField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class PerspectiveCamera - { - - private Point cameraViewPointField; - - private Direction cameraDirectionField; - - private Direction cameraUpVectorField; - - private double fieldOfViewField; - - //initialize fields - public PerspectiveCamera() - { - CameraViewPoint = new Point(); - CameraDirection = new Direction(); - CameraUpVector = new Direction(); - } - - /// - public Point CameraViewPoint - { - get { return this.cameraViewPointField; } - set { this.cameraViewPointField = value; } - } - - /// - public Direction CameraDirection - { - get { return this.cameraDirectionField; } - set { this.cameraDirectionField = value; } - } - - /// - public Direction CameraUpVector - { - get { return this.cameraUpVectorField; } - set { this.cameraUpVectorField = value; } - } - - /// - public double FieldOfView - { - get { return this.fieldOfViewField; } - set { this.fieldOfViewField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class OrthogonalCamera - { - - private Point cameraViewPointField; - - private Direction cameraDirectionField; - - private Direction cameraUpVectorField; - - private double viewToWorldScaleField; - - //initialize fields - public OrthogonalCamera() - { - CameraViewPoint = new Point(); - CameraDirection = new Direction(); - CameraUpVector = new Direction(); - } - - /// - public Point CameraViewPoint - { - get { return this.cameraViewPointField; } - set { this.cameraViewPointField = value; } - } - - /// - public Direction CameraDirection - { - get { return this.cameraDirectionField; } - set { this.cameraDirectionField = value; } - } - - /// - public Direction CameraUpVector - { - get { return this.cameraUpVectorField; } - set { this.cameraUpVectorField = value; } - } - - /// - public double ViewToWorldScale - { - get { return this.viewToWorldScaleField; } - set { this.viewToWorldScaleField = value; } - } - } - - - - /// - /// Custom BCFier field to support 2D views in Revit - /// EXPERIMENTAL - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class SheetCamera - { - - private Point topLeft; - - private Point bottomRight; - - private int sheetID; - - private string sheetName; - - public SheetCamera() - { - TopLeft = new Point(); - BottomRight = new Point(); - } - - /// - public Point TopLeft - { - get { return this.topLeft; } - set { this.topLeft = value; } - } - - /// - public Point BottomRight - { - get { return this.bottomRight; } - set { this.bottomRight = value; } - } - - /// - public int SheetID - { - get { return this.sheetID; } - set { this.sheetID = value; } - } - - /// - public string SheetName - { - get { return this.sheetName; } - set { this.sheetName = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class ComponentVisibility - { - - private Component[] exceptionsField; - - private bool defaultVisibilityField; - - private bool defaultVisibilityFieldSpecified; - - /// - [System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)] - public Component[] Exceptions - { - get { return this.exceptionsField; } - set { this.exceptionsField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool DefaultVisibility - { - get { return this.defaultVisibilityField; } - set { this.defaultVisibilityField = value; } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool DefaultVisibilitySpecified - { - get { return this.defaultVisibilityFieldSpecified; } - set { this.defaultVisibilityFieldSpecified = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class Component - { - - private string originatingSystemField; - - private string authoringToolIdField; - - private string ifcGuidField; - - /// - public string OriginatingSystem - { - get { return this.originatingSystemField; } - set { this.originatingSystemField = value; } - } - - /// - public string AuthoringToolId - { - get { return this.authoringToolIdField; } - set { this.authoringToolIdField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "normalizedString")] - public string IfcGuid - { - get { return this.ifcGuidField; } - set { this.ifcGuidField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class ComponentColoringColor - { - - private Component[] componentField; - - private string colorField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Component")] - public Component[] Component - { - get { return this.componentField; } - set { this.componentField = value; } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "normalizedString")] - public string Color - { - get { return this.colorField; } - set { this.colorField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] - public partial class VisualizationInfoBitmap - { - - private BitmapFormat bitmapField; - - private string referenceField; - - private Point locationField; - - private Direction normalField; - - private Direction upField; - - private double heightField; - - /// - public BitmapFormat Bitmap - { - get { return this.bitmapField; } - set { this.bitmapField = value; } - } - - /// - public string Reference - { - get { return this.referenceField; } - set { this.referenceField = value; } - } - - /// - public Point Location - { - get { return this.locationField; } - set { this.locationField = value; } - } - - /// - public Direction Normal - { - get { return this.normalField; } - set { this.normalField = value; } - } - - /// - public Direction Up - { - get { return this.upField; } - set { this.upField = value; } - } - - /// - public double Height - { - get { return this.heightField; } - set { this.heightField = value; } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1586.0")] - [System.SerializableAttribute()] - public enum BitmapFormat - { - - /// - PNG, - - /// - JPG, - } - -} diff --git a/Bcfier/Bcf/BcfContainer.cs b/Bcfier/Bcf/BcfContainer.cs deleted file mode 100755 index 561cd10e..00000000 --- a/Bcfier/Bcf/BcfContainer.cs +++ /dev/null @@ -1,550 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Text; -using System.Windows; -using System.Xml.Serialization; -using Bcfier.Bcf.Bcf2; -using Bcfier.Data.Utils; -using Bcfier.Data; - -namespace Bcfier.Bcf -{ - /// - /// Model View, binds to the tab control, contains the BCf files - /// and the main methods as save, open... - /// - public class BcfContainer : INotifyPropertyChanged - { - private ObservableCollection _bcfFiles { get; set; } - private int selectedReport { get; set; } - - public BcfContainer() - { - BcfFiles = new ObservableCollection(); - } - - - public ObservableCollection BcfFiles - { - get - { - return _bcfFiles; - } - - set - { - _bcfFiles = value; - NotifyPropertyChanged("BcfFiles"); - } - } - - public int SelectedReportIndex - { - get - { - return selectedReport; - } - - set - { - selectedReport = value; - NotifyPropertyChanged("SelectedReportIndex"); - } - } - - - public void NewFile() - { - BcfFiles.Add(new BcfFile()); - SelectedReportIndex = BcfFiles.Count - 1; - } - public void SaveFile(BcfFile bcf) - { - SaveBcfFile(bcf); - } - public void MergeFiles(BcfFile bcf) - { - var bcffiles = OpenBcfDialog(); - if (bcffiles == null) - return; - bcf.MergeBcfFile(bcffiles); - } - - public void OpenFile(string path) - { - var newbcf = OpenBcfFile(path); - BcfOpened(newbcf); - } - public void OpenFile() - { - var bcffiles = OpenBcfDialog(); - if (bcffiles == null) - return; - foreach (var bcffile in bcffiles) - { - if (bcffile == null) - continue; - BcfOpened(bcffile); - } - } - - private void BcfOpened(BcfFile newbcf) - { - if (newbcf != null) - { - BcfFiles.Add(newbcf); - SelectedReportIndex = BcfFiles.Count - 1; - if (newbcf.Issues.Any()) - newbcf.SelectedIssue = newbcf.Issues.First(); - - foreach (var issue in newbcf.Issues) - { - if (!Globals.OpenStatuses.Contains(issue.Topic.TopicStatus)) - Globals.OpenStatuses.Add(issue.Topic.TopicStatus); - - if (!Globals.OpenTypes.Contains(issue.Topic.TopicType)) - Globals.OpenTypes.Add(issue.Topic.TopicType); - } - } - } - - public void CloseFile(BcfFile bcf) - { - try - { - _bcfFiles.Remove(bcf); - Utils.DeleteDirectory(bcf.TempPath); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - - } - - /// - /// Removes all old statuses and types from the collection and adds the new ones, except for the selected one - /// This avoids having blank fields in case an existing value is removed - /// could probably be optimized - /// - public void UpdateDropdowns() - { - try - { - Globals.SetStatuses(UserSettings.Get("Stauses")); - Globals.SetTypes(UserSettings.Get("Types")); - - foreach (var bcf in BcfFiles) - { - foreach (var issue in bcf.Issues) - { - var oldStatus = issue.Topic.TopicStatus; - var oldType = issue.Topic.TopicType; - - //status - for (int i = issue.Topic.TopicStatusesCollection.Count - 1; i >= 0; i--) - { - if(issue.Topic.TopicStatusesCollection [i]!= oldStatus) - issue.Topic.TopicStatusesCollection.RemoveAt(i); - } - foreach (var status in Globals.AvailStatuses) - { - if (status != oldStatus || !issue.Topic.TopicStatusesCollection.Contains(status)) - issue.Topic.TopicStatusesCollection.Add(status); - } - //type - for (int i = issue.Topic.TopicTypesCollection.Count - 1; i >= 0; i--) - { - if (issue.Topic.TopicTypesCollection[i] != oldType) - issue.Topic.TopicTypesCollection.RemoveAt(i); - } - foreach (var type in Globals.AvailTypes) - { - if (type != oldType || !issue.Topic.TopicTypesCollection.Contains(type)) - issue.Topic.TopicTypesCollection.Add(type); - } - } - } - - } - - catch { - //suppress error - }; - - } - - - - - #region private methods - /// - /// Prompts a dialog to select one or more BCF files to open - /// - /// - private static IEnumerable OpenBcfDialog() - { - try - { - var openFileDialog1 = new Microsoft.Win32.OpenFileDialog(); - openFileDialog1.Filter = "BIM Collaboration Format (*.bcfzip)|*.bcfzip"; - openFileDialog1.DefaultExt = ".bcfzip"; - openFileDialog1.Multiselect = true; - openFileDialog1.RestoreDirectory = true; - openFileDialog1.CheckFileExists = true; - openFileDialog1.CheckPathExists = true; - var result = openFileDialog1.ShowDialog(); // Show the dialog. - - if (result == true) // Test result. - { - return openFileDialog1.FileNames.Select(OpenBcfFile).ToList(); - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - - /// - /// Logic that extracts files from a bcfzip and deserializes them - /// - /// Path to the .bcfzip file - /// - private static BcfFile OpenBcfFile(string bcfzipfile) - { - var bcffile = new BcfFile(); - try - { - if (!File.Exists(bcfzipfile) || !String.Equals(Path.GetExtension(bcfzipfile), ".bcfzip", StringComparison.InvariantCultureIgnoreCase)) - return bcffile; - - - bcffile.Filename = Path.GetFileNameWithoutExtension(bcfzipfile); - bcffile.Fullname = bcfzipfile; - - using (ZipArchive archive = ZipFile.OpenRead(bcfzipfile)) - { - archive.ExtractToDirectory(bcffile.TempPath); - } - - var dir = new DirectoryInfo(bcffile.TempPath); - - var projectFile = Path.Combine(bcffile.TempPath, "project.bcfp"); - if (File.Exists(projectFile)) - { - var project = DeserializeProject(projectFile); - var g = Guid.NewGuid(); - Guid.TryParse(project.Project.ProjectId, out g); - bcffile.ProjectId = g; - } - - - //ADD ISSUES FOR EACH SUBFOLDER - - foreach (var folder in dir.GetDirectories()) - { - //An issue needs at least the markup file - var markupFile = Path.Combine(folder.FullName, "markup.bcf"); - if (!File.Exists(markupFile)) - continue; - - var bcfissue = DeserializeMarkup(markupFile); - - - if (bcfissue == null) - continue; - - //Is a BCF 2 file, has multiple viewpoints - if (bcfissue.Viewpoints != null && bcfissue.Viewpoints.Any()) - { - foreach (var viewpoint in bcfissue.Viewpoints) - { - string viewpointpath = Path.Combine(folder.FullName, viewpoint.Viewpoint); - if (File.Exists(viewpointpath)) - { - //deserializing the viewpoint into the issue - viewpoint.VisInfo = DeserializeViewpoint(viewpointpath); - viewpoint.SnapshotPath = Path.Combine(folder.FullName, viewpoint.Snapshot); - } - } - } - //Is a BCF 1 file, only one viewpoint - //there is no Viewpoints tag in the markup - //update it to BCF 2 - else - { - bcfissue.Viewpoints = new ObservableCollection(); - string viewpointFile = Path.Combine(folder.FullName, "viewpoint.bcfv"); - if (File.Exists(viewpointFile)) - { - bcfissue.Viewpoints.Add(new ViewPoint(true) - { - VisInfo = DeserializeViewpoint(viewpointFile), - SnapshotPath = Path.Combine(folder.FullName, "snapshot.png"), - }); - //update the comments - foreach (var comment in bcfissue.Comment) - { - comment.Viewpoint = new CommentViewpoint(); - comment.Viewpoint.Guid = bcfissue.Viewpoints.First().Guid; - } - } - } - bcfissue.Comment = new ObservableCollection(bcfissue.Comment.OrderBy(x => x.Date)); - try - { - bcfissue.Viewpoints = new ObservableCollection(bcfissue.Viewpoints.OrderBy(x => x.Index)); - } - catch { } - //register the collectionchanged events, - //it is needed since deserialization overwrites the ones set in the constructor - bcfissue.RegisterEvents(); - //ViewComment stuff - bcffile.Issues.Add(bcfissue); - } - try - { - bcffile.Issues = new ObservableCollection(bcffile.Issues.OrderBy(x => x.Topic.Index)); - } - catch { } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return bcffile; - } - - /// - /// Serializes to a bcfzip and saves it to disk - /// - /// - /// - private static bool SaveBcfFile(BcfFile bcffile) - { - try - { - if (bcffile.Issues.Count == 0) - { - MessageBox.Show("The current BCF Report is empty.", "No Issue", MessageBoxButton.OK, MessageBoxImage.Error); - return false; - } - if (!Directory.Exists(bcffile.TempPath)) - Directory.CreateDirectory(bcffile.TempPath); - // Show save file dialog box - string name = !string.IsNullOrEmpty(bcffile.Filename) - ? bcffile.Filename - : "New BCF Report"; - string filename = SaveBcfDialog(name); - - // Process save file dialog box results - if (string.IsNullOrWhiteSpace(filename)) - return false; - var bcfProject = new ProjectExtension - { - Project = new Project - { - Name =string.IsNullOrEmpty(bcffile.ProjectName) ? bcffile.Filename : bcffile.ProjectName, - ProjectId = bcffile.ProjectId.Equals(Guid.Empty) ? Guid.NewGuid().ToString() : bcffile.ProjectId.ToString() - }, - ExtensionSchema = "" - - }; - var bcfVersion = new Bcf2.Version { VersionId = "2.1", DetailedVersion = "2.1" }; - - var serializerP = new XmlSerializer(typeof(ProjectExtension)); - Stream writerP = new FileStream(Path.Combine(bcffile.TempPath, "project.bcfp"), FileMode.Create); - serializerP.Serialize(writerP, bcfProject); - writerP.Close(); - - var serializerVers = new XmlSerializer(typeof(Bcf2.Version)); - Stream writerVers = new FileStream(Path.Combine(bcffile.TempPath, "bcf.version"), FileMode.Create); - serializerVers.Serialize(writerVers, bcfVersion); - writerVers.Close(); - - var serializerV = new XmlSerializer(typeof(VisualizationInfo)); - var serializerM = new XmlSerializer(typeof(Markup)); - - var i = 0; - foreach (var issue in bcffile.Issues) - { - //set topic index - issue.Topic.Index = i; - issue.Topic.IndexSpecified = true; - i++; - - // serialize the object, and close the TextWriter - string issuePath = Path.Combine(bcffile.TempPath, issue.Topic.Guid); - if (!Directory.Exists(issuePath)) - Directory.CreateDirectory(issuePath); - - //set viewpoint index - for (var l = 0; l < issue.Viewpoints.Count; l++) - { - issue.Viewpoints[l].Index = l; - issue.Viewpoints[l].IndexSpecified = true; - } - - //BCF 1 compatibility - //there needs to be a view whose viewpoint and snapshot are named as follows and not with a guid - //uniqueness is still guarenteed by the guid field - if (issue.Viewpoints.Any() && (issue.Viewpoints.Count == 1 || issue.Viewpoints.All(o => o.Viewpoint != "viewpoint.bcfv"))) - { - if (File.Exists(Path.Combine(issuePath, issue.Viewpoints[0].Viewpoint))) - File.Delete(Path.Combine(issuePath, issue.Viewpoints[0].Viewpoint)); - issue.Viewpoints[0].Viewpoint = "viewpoint.bcfv"; - if (File.Exists(Path.Combine(issuePath, issue.Viewpoints[0].Snapshot))) - File.Move(Path.Combine(issuePath, issue.Viewpoints[0].Snapshot), Path.Combine(issuePath, "snapshot.png")); - issue.Viewpoints[0].Snapshot = "snapshot.png"; - } - //serialize markup with updated content - Stream writerM = new FileStream(Path.Combine(issuePath, "markup.bcf"), FileMode.Create); - serializerM.Serialize(writerM, issue); - writerM.Close(); - //serialize views - foreach (var bcfViewpoint in issue.Viewpoints) - { - Stream writerV = new FileStream(Path.Combine(issuePath, bcfViewpoint.Viewpoint), FileMode.Create); - serializerV.Serialize(writerV, bcfViewpoint.VisInfo); - writerV.Close(); - } - - - } - - //overwrite, without doubts - if (File.Exists(filename)) - File.Delete(filename); - - //added encoder to address backslashes issue #11 - //issue: https://github.com/teocomi/BCFier/issues/11 - //ref: http://stackoverflow.com/questions/27289115/system-io-compression-zipfile-net-4-5-output-zip-in-not-suitable-for-linux-mac - ZipFile.CreateFromDirectory(bcffile.TempPath, filename, CompressionLevel.Optimal, false, new ZipEncoder()); - - //Open browser at location - Uri uri2 = new Uri(filename); - string reportname = Path.GetFileName(uri2.LocalPath); - - if (File.Exists(filename)) - { - string argument = @"/select, " + filename; - System.Diagnostics.Process.Start("explorer.exe", argument); - } - bcffile.HasBeenSaved = true; - bcffile.Filename = reportname; - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return true; - } - - /// - /// Prompts a the user to select where to save the bcfzip - /// - /// - /// - private static string SaveBcfDialog(string filename) - { - var saveFileDialog = new Microsoft.Win32.SaveFileDialog - { - Title = "Save as BCF report file (.bcfzip)", - FileName = filename, - DefaultExt = ".bcfzip", - Filter = "BIM Collaboration Format (*.bcfzip)|*.bcfzip" - }; - - //if it goes fine I return the filename, otherwise empty - var result = saveFileDialog.ShowDialog(); - return result == true ? saveFileDialog.FileName : ""; - } - - private static VisualizationInfo DeserializeViewpoint(string path) - { - VisualizationInfo output = null; - try - { - - using (var viewpointFile = new FileStream(path, FileMode.Open)) - { - var serializerS = new XmlSerializer(typeof(VisualizationInfo)); - output = serializerS.Deserialize(viewpointFile) as VisualizationInfo; - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return output; - } - private static Markup DeserializeMarkup(string path) - { - Markup output = null; - try - { - using (var markupFile = new FileStream(path, FileMode.Open)) - { - var serializerM = new XmlSerializer(typeof(Markup)); - output = serializerM.Deserialize(markupFile) as Markup; - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return output; - } - - private static ProjectExtension DeserializeProject(string path) - { - ProjectExtension output = null; - try - { - using (var markupFile = new FileStream(path, FileMode.Open)) - { - var serializerM = new XmlSerializer(typeof(ProjectExtension)); - output = serializerM.Deserialize(markupFile) as ProjectExtension; - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return output; - } - - - #endregion - - [field: NonSerialized] - public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String info) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(info)); - } - } - } - - class ZipEncoder : UTF8Encoding - { - public ZipEncoder() - { - - } - public override byte[] GetBytes(string s) - { - s = s.Replace("\\", "/"); - return base.GetBytes(s); - } - } -} diff --git a/Bcfier/Bcf/BcfFile.cs b/Bcfier/Bcf/BcfFile.cs deleted file mode 100755 index fc00f99b..00000000 --- a/Bcfier/Bcf/BcfFile.cs +++ /dev/null @@ -1,300 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Windows; -using System.Windows.Data; -using Bcfier.Bcf.Bcf2; -using Bcfier.Data.Utils; - -namespace Bcfier.Bcf -{ - /// - /// View Model of a deserialized BCF - /// - public class BcfFile : INotifyPropertyChanged - { - private Guid id; - public string TempPath { get; set; } - public string Fullname { get; set; } - public Guid ProjectId { get; set; } - public string ProjectName { get; set; } - private string _filename; - private bool _hasBeenSaved; - private ObservableCollection _issues; - private Markup _selectedIssue; - private string _textSearch; - private ListCollectionView _view; - - public BcfFile() - { - _hasBeenSaved = true; - Filename = "New BCF Report"; - Id = Guid.NewGuid(); - TempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "BCFier", Id.ToString()); - Issues = new ObservableCollection(); - } - public bool HasBeenSaved - { - get - { - return _hasBeenSaved; - } - - set - { - _hasBeenSaved = value; - NotifyPropertyChanged("HasBeenSaved"); - } - } - public Guid Id - { - get - { - return id; - } - - set - { - id = value; - NotifyPropertyChanged("Id"); - } - } - - public string Filename - { - get - { - return _filename; - } - - set - { - _filename = value; - NotifyPropertyChanged("Filename"); - } - } - - public ObservableCollection Issues - { - get { return _issues; } - - set - { - _issues = value; - this._view = new ListCollectionView(this.Issues); - NotifyPropertyChanged("Issues"); - } - } - - public Markup SelectedIssue - { - get - { - return _selectedIssue; - } - - set - { - _selectedIssue = value; - NotifyPropertyChanged("SelectedIssue"); - } - } - - - public ICollectionView View - { - get - { - return this._view; - } - } - - public string TextSearch - { - get { return _textSearch; } - set - { - _textSearch = value; - NotifyPropertyChanged("TextSearch"); - - if (String.IsNullOrEmpty(value)) - View.Filter = null; - else - View.Filter = Filter; - } - } - - private bool Filter(object o) - { - var issue = (Markup)o; - if (issue == null) - return false; - if (issue.Topic != null && ((issue.Topic.Title != null && issue.Topic.Title.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant())) || - (issue.Topic.Description != null && issue.Topic.Description.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant()))) || - issue.Comment != null && issue.Comment.Any(x => x.Comment1.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant())) - - ) - return true; - return false; - } - - public void RemoveIssues(IEnumerable selectetitems) - { - foreach (var item in selectetitems) - { - Utils.DeleteDirectory(Path.Combine(TempPath, item.Topic.Guid)); - Issues.Remove(item); - } - HasBeenSaved = false; - } - - public void RemoveComment(IEnumerable selectetitems, Markup issue) - { - foreach (var item in selectetitems) - { - issue.Comment.Remove(item); - } - HasBeenSaved = false; - } - public void RemoveComment(Comment comment, Markup issue) - { - issue.Comment.Remove(comment); - HasBeenSaved = false; - } - public void RemoveView(ViewPoint view, Markup issue, bool delComm) - { - - if (File.Exists(Path.Combine(TempPath, issue.Topic.Guid, view.Viewpoint))) - File.Delete(Path.Combine(TempPath, issue.Topic.Guid, view.Viewpoint)); - if (File.Exists(view.SnapshotPath)) - File.Delete(view.SnapshotPath); - - var guid = view.Guid; - issue.Viewpoints.Remove(view); - //remove comments associated with that view - var viewcomments = issue.Comment.Where(x => x.Viewpoint != null && x.Viewpoint.Guid == guid).ToList(); - - if (!viewcomments.Any()) - return; - - foreach (var viewcomm in viewcomments) - { - if (delComm) - issue.Comment.Remove(viewcomm); - else - viewcomm.Viewpoint = null; - } - - - - HasBeenSaved = false; - } - public void RemoveView(IEnumerable selectetitems, Markup issue, bool delComm) - { - foreach (var item in selectetitems) - { - if (File.Exists(Path.Combine(TempPath, issue.Topic.Guid, item.Viewpoint))) - File.Delete(Path.Combine(TempPath, issue.Topic.Guid, item.Viewpoint)); - if (File.Exists(item.SnapshotPath)) - File.Delete(item.SnapshotPath); - - var guid = item.Guid; - issue.Viewpoints.Remove(item); - //remove comments associated with that view - var viewcomments = issue.Comment.Where(x => x.Viewpoint.Guid == guid).ToList(); - foreach (var viewcomm in viewcomments) - { - if (delComm) - issue.Comment.Remove(viewcomm); - else - viewcomm.Viewpoint = null; - } - - - } - HasBeenSaved = false; - } - - public void MergeBcfFile(IEnumerable bcfFiles) - { - try - { - - foreach (var bcf in bcfFiles) - { - foreach (var mergedIssue in bcf.Issues) - { - //it's a new issue - if (!Issues.Any(x => x.Topic != null && mergedIssue.Topic != null && x.Topic.Guid == mergedIssue.Topic.Guid)) - { - string sourceDir = Path.Combine(bcf.TempPath, mergedIssue.Topic.Guid); - string destDir = Path.Combine(TempPath, mergedIssue.Topic.Guid); - - Directory.Move(sourceDir, destDir); - //update path set for binding - foreach (var view in mergedIssue.Viewpoints) - { - view.SnapshotPath = Path.Combine(TempPath, mergedIssue.Topic.Guid, view.Snapshot); - } - Issues.Add(mergedIssue); - - } - //it exists, let's loop comments and views - else - { - var issue = Issues.First(x => x.Topic.Guid == mergedIssue.Topic.Guid); - var newComments = mergedIssue.Comment.Where(x => issue.Comment.All(y => y.Guid != x.Guid)).ToList(); - if (newComments.Any()) - foreach (var newComment in newComments) - issue.Comment.Add(newComment); - //sort comments - issue.Comment = new ObservableCollection(issue.Comment.OrderByDescending(x => x.Date)); - - var newViews = mergedIssue.Viewpoints.Where(x => issue.Viewpoints.All(y => y.Guid != x.Guid)).ToList(); - if (newViews.Any()) - foreach (var newView in newViews) - { - //to avoid conflicts in case both contain a snapshot.png or viewpoint.bcfv - //img to be merged - string sourceFile = newView.SnapshotPath; - //assign new safe name based on guid - newView.Snapshot = newView.Guid + ".png"; - //set new temp path for binding - newView.SnapshotPath = Path.Combine(TempPath, issue.Topic.Guid, newView.Snapshot); - //assign new safe name based on guid - newView.Viewpoint = newView.Guid + ".bcfv"; - File.Move(sourceFile, newView.SnapshotPath); - issue.Viewpoints.Add(newView); - - - } - } - } - Utils.DeleteDirectory(bcf.TempPath); - } - HasBeenSaved = false; - - - - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - - } - - [field: NonSerialized] - public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged(String info) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(info)); - } - } - } -} diff --git a/Bcfier/Bcfier.csproj b/Bcfier/Bcfier.csproj deleted file mode 100644 index a79b023a..00000000 --- a/Bcfier/Bcfier.csproj +++ /dev/null @@ -1,387 +0,0 @@ - - - - - Debug - AnyCPU - {503CE2C1-09D7-4F15-BB42-86196EE01ED4} - Library - Properties - Bcfier - Bcfier - v4.5 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - - - - true - bin\ManualObfuscation\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - false - - - Assets\icon.ico - - - true - bin\Debug-2015\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2016\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2017\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2015\ - - - bin\Release-2016\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2017\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2018\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2018\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2019\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2019\ - TRACE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2021\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release-2021\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - bin\Release2020\ - TRACE - true - pdbonly - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-2020\ - DEBUG;TRACE - full - AnyCPU - 7.3 - prompt - MinimumRecommendedRules.ruleset - - - - ..\packages\DotNetZip.1.13.8\lib\net40\DotNetZip.dll - - - ..\packages\gong-wpf-dragdrop.1.1.0\lib\net45\GongSolutions.Wpf.DragDrop.dll - - - - ..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll - - - - - - - - - - - - - - - 4.0 - - - - - - - - Properties\AssemblyVersionInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IssueListStyle.xaml - - - - - BcfierPanel.xaml - - - BcfReportPanel.xaml - - - AddView.xaml - - - ComponentsList.xaml - - - NewVersion.xaml - - - Settings.xaml - - - SnapWin.xaml - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Data/AttachedProperties/CtrlEnterKeyDown.cs b/Bcfier/Data/AttachedProperties/CtrlEnterKeyDown.cs deleted file mode 100644 index 5288bc3b..00000000 --- a/Bcfier/Data/AttachedProperties/CtrlEnterKeyDown.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using System.Windows.Controls; -using System.Windows.Documents; - -namespace Bcfier.Data.AttachedProperties -{ - /// - /// Binds Ctrl+Enter events to a command - /// Edited from: http://stackoverflow.com/questions/4834227/invoke-command-when-enter-key-is-pressed-in-xaml - /// - public sealed class CtrlEnterKeyDown - { - #region Properties - - #region Command - - public static ICommand GetCommand(DependencyObject obj) - { - return (ICommand)obj.GetValue(CommandProperty); - } - - public static void SetCommand(DependencyObject obj, ICommand value) - { - obj.SetValue(CommandProperty, value); - } - - public static readonly DependencyProperty CommandProperty = - DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CtrlEnterKeyDown), - new PropertyMetadata(null, OnCommandChanged)); - - #endregion Command - - #region CommandArgument - - public static object GetCommandArgument(DependencyObject obj) - { - return (object)obj.GetValue(CommandArgumentProperty); - } - - public static void SetCommandArgument(DependencyObject obj, object value) - { - obj.SetValue(CommandArgumentProperty, value); - } - - public static readonly DependencyProperty CommandArgumentProperty = - DependencyProperty.RegisterAttached("CommandArgument", typeof(object), typeof(CtrlEnterKeyDown), - new PropertyMetadata(null, OnCommandArgumentChanged)); - - #endregion CommandArgument - - #region HasCommandArgument - - - private static bool GetHasCommandArgument(DependencyObject obj) - { - return (bool)obj.GetValue(HasCommandArgumentProperty); - } - - private static void SetHasCommandArgument(DependencyObject obj, bool value) - { - obj.SetValue(HasCommandArgumentProperty, value); - } - - private static readonly DependencyProperty HasCommandArgumentProperty = - DependencyProperty.RegisterAttached("HasCommandArgument", typeof(bool), typeof(CtrlEnterKeyDown), - new PropertyMetadata(false)); - - - #endregion HasCommandArgument - - #endregion Propreties - - #region Event Handling - - private static void OnCommandArgumentChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) - { - SetHasCommandArgument(o, true); - } - - private static void OnCommandChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) - { - FrameworkElement element = o as FrameworkElement; - if (element != null) - { - if (e.NewValue == null) - { - element.KeyDown -= new KeyEventHandler(FrameworkElement_KeyDown); - } - else if (e.OldValue == null) - { - element.KeyDown += new KeyEventHandler(FrameworkElement_KeyDown); - } - } - } - - private static void FrameworkElement_KeyDown(object sender, KeyEventArgs e) - { - - if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Enter) - { - DependencyObject o = sender as DependencyObject; - ICommand command = GetCommand(sender as DependencyObject); - - FrameworkElement element = e.OriginalSource as FrameworkElement; - if (element != null) - { - // If the command argument has been explicitly set (even to NULL) - if (GetHasCommandArgument(o)) - { - object commandArgument = GetCommandArgument(o); - - // Execute the command - if (command.CanExecute(commandArgument)) - { - command.Execute(commandArgument); - } - } - else if (command.CanExecute(element.DataContext)) - { - command.Execute(element.DataContext); - } - } - } - } - - #endregion - } -} diff --git a/Bcfier/Data/AttachedProperties/NavigationService.cs b/Bcfier/Data/AttachedProperties/NavigationService.cs deleted file mode 100644 index c877e965..00000000 --- a/Bcfier/Data/AttachedProperties/NavigationService.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; - -namespace Bcfier.Data.AttachedProperties -{ - //Copied from http://stackoverflow.com/questions/861409/wpf-making-hyperlinks-clickable - /// - /// Renders the text of the comments as clickable links if detects URLs or local PATHs - /// - public static class NavigationService - { - //URL - // (?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)? - //PATH - //((\\\\[a-zA-Z0-9-]+\\[a-zA-Z0-9`~!@#$%^&(){}'._-]+([ ]+[a-zA-Z0-9`~!@#$%^&(){}'._-]+)*)|([a-zA-Z]:))(\\[^ \\/:*?""<>|]+([ ]+[^ \\/:*?""<>|]+)*)*\\? - private static readonly Regex RE_URL = new Regex(@"(?(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?)|(?\[(((\\\\[a-zA-Z0-9-]+\\[a-zA-Z0-9`~!@#$%^&(){}'._-]+([ ]+[a-zA-Z0-9`~!@#$%^&(){}'._-]+)*)|([a-zA-Z]:))(\\[^ \\/:*?""<>|]+([ ]+[^ \\/:*?""<>|]+)*)*\\?)\])"); - - public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached( - "Text", - typeof(string), - typeof(NavigationService), - new PropertyMetadata(null, OnTextChanged) - ); - - public static string GetText(DependencyObject d) - { return d.GetValue(TextProperty) as string; } - - public static void SetText(DependencyObject d, string value) - { d.SetValue(TextProperty, value); } - - private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - try { - var text_block = d as TextBlock; - if (text_block == null) - return; - - text_block.Inlines.Clear(); - - var new_text = (string)e.NewValue; - if (string.IsNullOrEmpty(new_text)) - return; - - // Find all URLs using a regular expression - int last_pos = 0; - foreach (Match match in RE_URL.Matches(new_text)) - { - var matchString = match.Value.Replace("[","").Replace("]",""); - Uri url = null; - if (!Uri.TryCreate(matchString, UriKind.RelativeOrAbsolute, out url)) - continue; - // Copy raw string from the last position up to the match - if (match.Index != last_pos) - { - var raw_text = new_text.Substring(last_pos, match.Index - last_pos); - text_block.Inlines.Add(new Run(raw_text)); - } - - // Create a hyperlink for the match - var link = new Hyperlink(new Run(matchString)) - { - NavigateUri = url - }; - link.Click += OnUrlClick; - - text_block.Inlines.Add(link); - - // Update the last matched position - last_pos = match.Index + match.Length; - } - - // Finally, copy the remainder of the string - if (last_pos < new_text.Length) - text_block.Inlines.Add(new Run(new_text.Substring(last_pos))); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - - private static void OnUrlClick(object sender, RoutedEventArgs e) - { - var link = (Hyperlink)sender; - // Do something with link.NavigateUri like: - try { - Process.Start(link.NavigateUri.ToString()); - } - catch (System.Exception ex1) - { - Console.WriteLine(ex1.Message); - } - } - } -} diff --git a/Bcfier/Data/Commands.cs b/Bcfier/Data/Commands.cs deleted file mode 100644 index 676ea46f..00000000 --- a/Bcfier/Data/Commands.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Controls; -using System.Windows.Input; -using Bcfier.UserControls; - -namespace Bcfier.Data -{ - /// - /// Commands used by the application - /// - public static class Commands - { - //issues - public static readonly RoutedCommand AddIssue = new RoutedCommand("AddIssue", typeof(Button)); - public static readonly RoutedCommand AddIssues = new RoutedCommand("AddIssues", typeof(Button)); - public static readonly RoutedCommand DeleteIssues = new RoutedCommand("DeleteIssues", typeof(Button)); - //comments - public static readonly RoutedCommand AddComment = new RoutedCommand("AddComment", typeof(Button)); - public static readonly RoutedCommand DeleteComments = new RoutedCommand("DeleteComments", typeof(Button)); - //viewpoints - public static readonly RoutedCommand AddView = new RoutedCommand("AddView", typeof(Button)); - public static readonly RoutedCommand DeleteViews = new RoutedCommand("DeleteViews", typeof(Button)); - public static readonly RoutedCommand OpenView = new RoutedCommand("OpenView", typeof(Button)); - public static readonly RoutedCommand OpenSnapshot = new RoutedCommand("OpenSnapshot", typeof(Button)); - public static readonly RoutedCommand OpenComponents = new RoutedCommand("OpenComponents", typeof(Button)); - - public static readonly RoutedCommand CloseBcf = new RoutedCommand("CloseBcf", typeof(Button)); - } -} diff --git a/Bcfier/Data/Globals.cs b/Bcfier/Data/Globals.cs deleted file mode 100644 index 52e693ec..00000000 --- a/Bcfier/Data/Globals.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bcfier.Data -{ - public static class Globals - { - public static List OpenStatuses = new List(); - public static List OpenTypes = new List(); - - private static IEnumerable availStatuses = new List(); - private static IEnumerable availTypes = new List(); - - //join with the list of statuses from other open BCFs - public static IEnumerable AvailStatuses - { - get { return availStatuses.Union(OpenStatuses); } - } - - public static void SetStatuses(string statusString) - { - availStatuses = new List(statusString.Split(new char[] { ',' }).Select(o => o.Trim())); - } - - //join with the list of types from other open BCFs - public static IEnumerable AvailTypes - { - get { return availTypes.Union(OpenTypes); } - } - - public static void SetTypes(string statusTypes) - { - availTypes = new List(statusTypes.Split(new char[] { ',' }).Select(o => o.Trim())); - } - } -} diff --git a/Bcfier/Data/Utils/IfcGuid.cs b/Bcfier/Data/Utils/IfcGuid.cs deleted file mode 100644 index 4dfaeb9b..00000000 --- a/Bcfier/Data/Utils/IfcGuid.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Diagnostics; -using System.Globalization; - -namespace Bcfier.Data.Utils -{ - /// - /// Conversion methods between an IFC - /// encoded GUID string and a .NET GUID. - /// This is a translation of the C code - /// found here: - /// http://www.iai-tech.org/ifc/IFC2x3/TC1/html/index.htm - /// - public static class IfcGuid - { - #region Private Members - /// - /// The replacement table - /// - private static readonly char[] base64Chars = new char[] - { '0','1','2','3','4','5','6','7','8','9' - , 'A','B','C','D','E','F','G','H','I','J' - , 'K','L','M','N','O','P','Q','R','S','T' - , 'U','V','W','X','Y','Z','a','b','c','d' - , 'e','f','g','h','i','j','k','l','m','n' - , 'o','p','q','r','s','t','u','v','w','x' - , 'y','z','_','$' }; - - /// - /// Conversion of an integer into characters - /// with base 64 using the table base64Chars - /// - /// The number to convert - /// The result char array to write to - /// The position in the char array to start writing - /// The length to write - /// - static void cv_to_64( uint number, ref char[] result, int start, int len ) - { - uint act; - int iDigit, nDigits; - - Debug.Assert( len <= 4 ); - act = number; - nDigits = len; - - for( iDigit = 0; iDigit < nDigits; iDigit++ ) - { - result[start + len - iDigit - 1] = base64Chars[( int ) ( act % 64 )]; - act /= 64; - } - Debug.Assert( act == 0, "Logic failed, act was not null: " + act.ToString() ); - return; - } - - /// - /// The reverse function to calculate - /// the number from the characters - /// - /// The char array to convert from - /// Position in array to start read - /// The length to read - /// The calculated nuber - static uint cv_from_64( char[] str, int start, int len ) - { - int i, j, index; - uint res = 0; - Debug.Assert( len <= 4 ); - - for( i = 0; i < len; i++ ) - { - index = -1; - for( j = 0; j < 64; j++ ) - { - if( base64Chars[j] == str[start + i] ) - { - index = j; - break; - } - } - Debug.Assert( index >= 0 ); - res = res * 64 + ( ( uint ) index ); - } - return res; - } - #endregion // Private Members - - #region Conversion Methods - /// - /// Reconstruction of the GUID - /// from an IFC GUID string (base64) - /// - /// The GUID string to convert. Must be 22 characters long - /// GUID correspondig to the string - public static Guid FromIfcGUID( string guid ) - { - Debug.Assert( guid.Length == 22, "Input string must not be longer that 22 chars" ); - uint[] num = new uint[6]; - char[] str = guid.ToCharArray(); - int n = 2, pos = 0, i; - for( i = 0; i < 6; i++ ) - { - num[i] = cv_from_64( str, pos, n ); - pos += n; n = 4; - } - - int a = ( int ) ( ( num[0] * 16777216 + num[1] ) ); - short b = ( short ) ( num[2] / 256 ); - short c = ( short ) ( ( num[2] % 256 ) * 256 + num[3] / 65536 ); - byte[] d = new byte[8]; - d[0] = Convert.ToByte( ( num[3] / 256 ) % 256 ); - d[1] = Convert.ToByte( num[3] % 256 ); - d[2] = Convert.ToByte( num[4] / 65536 ); - d[3] = Convert.ToByte( ( num[4] / 256 ) % 256 ); - d[4] = Convert.ToByte( num[4] % 256 ); - d[5] = Convert.ToByte( num[5] / 65536 ); - d[6] = Convert.ToByte( ( num[5] / 256 ) % 256 ); - d[7] = Convert.ToByte( num[5] % 256 ); - - return new Guid( a, b, c, d ); - } - - /// - /// Conversion of a GUID to a string - /// representing the GUID - /// - /// The GUID to convert - /// IFC (base64) encoded GUID string - public static string ToIfcGuid( Guid guid ) - { - uint[] num = new uint[6]; - char[] str = new char[22]; - int i, n; - byte[] b = guid.ToByteArray(); - - // Creation of six 32 Bit integers from the components of the GUID structure - num[0] = ( uint ) ( BitConverter.ToUInt32( b, 0 ) / 16777216 ); - num[1] = ( uint ) ( BitConverter.ToUInt32( b, 0 ) % 16777216 ); - num[2] = ( uint ) ( BitConverter.ToUInt16( b, 4 ) * 256 + BitConverter.ToUInt16( b, 6 ) / 256 ); - num[3] = ( uint ) ( ( BitConverter.ToUInt16( b, 6 ) % 256 ) * 65536 + b[8] * 256 + b[9] ); - num[4] = ( uint ) ( b[10] * 65536 + b[11] * 256 + b[12] ); - num[5] = ( uint ) ( b[13] * 65536 + b[14] * 256 + b[15] ); - - // Conversion of the numbers into a system using a base of 64 - n = 2; - int pos = 0; - for( i = 0; i < 6; i++ ) - { - cv_to_64( num[i], ref str, pos, n ); - pos += n; n = 4; - } - return new String( str ); - } - #endregion // Conversion Methods - - - #region Extension Methods - - // - //Get the Unique ID in encoded on IFC Format (base 64) - // - // - // - public static string IfcGUID(string UniqueId) - { - Guid episodeId = new Guid(UniqueId.Substring(0, 36)); - int elementId = int.Parse(UniqueId.Substring(37), NumberStyles.AllowHexSpecifier); - int last_32_bits = int.Parse(UniqueId.Substring(28, 8), NumberStyles.AllowHexSpecifier); - int xor = last_32_bits ^ elementId; - UniqueId = UniqueId.Substring(0, 28) + xor.ToString("x8"); - Guid guid = new Guid(UniqueId); - return ToIfcGuid(guid); - } - #endregion - - } -} diff --git a/Bcfier/Data/Utils/ImagingUtils.cs b/Bcfier/Data/Utils/ImagingUtils.cs deleted file mode 100644 index 122f6074..00000000 --- a/Bcfier/Data/Utils/ImagingUtils.cs +++ /dev/null @@ -1,245 +0,0 @@ -using System; -using System.IO; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; - -namespace Bcfier.Data.Utils -{ - public static class ImagingUtils - { - /// - /// Classes for working with images - /// - /// - /// - public static ImageSource ImageSourceFromPath(string sourcePath) - { - - try - { - //var image = BitmapFromPath(sourcePath); - //return ConvertBitmapTo96Dpi(image); - - var image = BitmapFromPath(sourcePath); - int width = image.PixelWidth; - int height = image.PixelHeight; - - const int maxWidth = 1500; - const int maxHeight = 1500; - if (width > maxWidth || height > maxHeight) - { - - double scale = (width > height) ? (double)width / (double)maxWidth : (double)height / (double)maxHeight; - int newHeight = Convert.ToInt32(height / scale); - int newWidth = Convert.ToInt32(width / scale); - - MessageBoxResult answer = MessageBox.Show( - string.Format("Image size is {0}x{1}, " - + "such a big image could increase A LOT the BCF file size. " - + "Do you want me to resize it to {2}x{3} for you?", width, height, newWidth, newHeight), "Attention!", - MessageBoxButton.YesNo, MessageBoxImage.Question); - if (answer == MessageBoxResult.Yes) - { - width = newWidth; - } - - } - - byte[] imageBytes = LoadImageData(sourcePath); - return CreateImage(imageBytes, width, 0); - - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - - public static void SaveImageSource(ImageSource image, string destPath) - { - try - { - var imageBytes = GetEncodedImageData(image, ".jpg"); - SaveImageData(imageBytes, destPath); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - - public static BitmapImage BitmapFromPath(string path) - { - try - { - var image = new BitmapImage(); - image.BeginInit(); - image.UriSource = new Uri(path); - image.CacheOption = BitmapCacheOption.OnLoad; - image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; - image.EndInit(); - return image; - } - catch - { - return null; - } - - } - public static BitmapSource ConvertBitmapTo96Dpi(BitmapImage bitmapImage) - { - try - { - double dpi = 96; - int width = bitmapImage.PixelWidth; - int height = bitmapImage.PixelHeight; - - if (width > 1500 || height > 1500) - { - string size = width.ToString() + "x" + height.ToString(); - int newWidth = 1500; - float scale = (float)newWidth / ((float)width / (float)height); - int newHeight = Convert.ToInt32(scale); - - MessageBoxResult answer = MessageBox.Show("Image size is " + size + ", " - + "such a big image could increase A LOT the BCF file size. " - + "Do you want me to resize it to " + newWidth.ToString() + "x" + newHeight.ToString() + " for you?", "Attention!", - MessageBoxButton.YesNo, MessageBoxImage.Question); - if (answer == MessageBoxResult.Yes) - { - width = newWidth; - height = newHeight; - } - - } - - int stride = width * 4; // 4 bytes per pixel - byte[] pixelData = new byte[stride * height]; - bitmapImage.CopyPixels(pixelData, stride, 0); - - return BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride); - } - - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - - private static byte[] LoadImageData(string filePath) - { - try - { - FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); - BinaryReader br = new BinaryReader(fs); - byte[] imageBytes = br.ReadBytes((int)fs.Length); - br.Close(); - fs.Close(); - return imageBytes; - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - - private static ImageSource CreateImage(byte[] imageData, int decodePixelWidth, int decodePixelHeight) - { - try - { - if (imageData == null) return null; - BitmapImage result = new BitmapImage(); - result.BeginInit(); - if (decodePixelWidth > 0) - { - result.DecodePixelWidth = decodePixelWidth; - } - if (decodePixelHeight > 0) - { - result.DecodePixelHeight = decodePixelHeight; - } - result.StreamSource = new MemoryStream(imageData); - result.CreateOptions = BitmapCreateOptions.None; - result.CacheOption = BitmapCacheOption.Default; - result.EndInit(); - return result; - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - - private static void SaveImageData(byte[] imageData, string filePath) - { - try - { - FileStream fs = new FileStream(filePath, FileMode.Create, - FileAccess.Write); - BinaryWriter bw = new BinaryWriter(fs); - bw.Write(imageData); - bw.Close(); - fs.Close(); - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - - private static byte[] GetEncodedImageData(ImageSource image, string preferredFormat) - { - try - { - byte[] result = null; - BitmapEncoder encoder = null; - switch (preferredFormat.ToLower()) - { - case ".jpg": - case ".jpeg": - encoder = new JpegBitmapEncoder(); - break; - case ".bmp": - encoder = new BmpBitmapEncoder(); - break; - case ".png": - encoder = new PngBitmapEncoder(); - break; - case ".tif": - case ".tiff": - encoder = new TiffBitmapEncoder(); - break; - case ".gif": - encoder = new GifBitmapEncoder(); - break; - case ".wmp": - encoder = new WmpBitmapEncoder(); - break; - } - if (image is BitmapSource) - { - MemoryStream stream = new MemoryStream(); - encoder.Frames.Add(BitmapFrame.Create(image as BitmapSource)); - encoder.Save(stream); - stream.Seek(0, SeekOrigin.Begin); - result = new byte[stream.Length]; - BinaryReader br = new BinaryReader(stream); - br.Read(result, 0, (int)stream.Length); - br.Close(); - stream.Close(); - } - return result; - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return null; - } - } -} diff --git a/Bcfier/Data/Utils/RelativeDate.cs b/Bcfier/Data/Utils/RelativeDate.cs deleted file mode 100644 index cc161ca4..00000000 --- a/Bcfier/Data/Utils/RelativeDate.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bcfier.Data.Utils -{ - /// - /// Convert a DateTime or string to a relative date - /// - public static class RelativeDate - { - public static string ToRelative(string DateString) - { - DateTime theDate = Convert.ToDateTime(DateString); - var thresholds = new Dictionary(); - int minute = 60; - int hour = 60 * minute; - int day = 24 * hour; - thresholds.Add(60, "{0} seconds ago"); - thresholds.Add(minute * 2, "a minute ago"); - thresholds.Add(45 * minute, "{0} minutes ago"); - thresholds.Add(120 * minute, "an hour ago"); - thresholds.Add(day, "{0} hours ago"); - thresholds.Add(day * 2, "yesterday"); - // thresholds.Add(day * 30, "{0} days ago"); - thresholds.Add(day * 365, "{0} days ago"); - thresholds.Add(long.MaxValue, "{0} years ago"); - - long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000; - foreach (long threshold in thresholds.Keys) - { - if (since < threshold) - { - TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks)); - return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString()); - } - } - return ""; - } - public static string ToRelative(DateTime theDate) - { - - var thresholds = new Dictionary(); - int minute = 60; - int hour = 60 * minute; - int day = 24 * hour; - thresholds.Add(60, "{0} seconds ago"); - thresholds.Add(minute * 2, "a minute ago"); - thresholds.Add(45 * minute, "{0} minutes ago"); - thresholds.Add(120 * minute, "an hour ago"); - thresholds.Add(day, "{0} hours ago"); - thresholds.Add(day * 2, "yesterday"); - // thresholds.Add(day * 30, "{0} days ago"); - thresholds.Add(day * 365, "{0} days ago"); - thresholds.Add(long.MaxValue, "{0} years ago"); - - long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000; - foreach (long threshold in thresholds.Keys) - { - if (since < threshold) - { - TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks)); - return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString()); - } - } - return ""; - } - } -} diff --git a/Bcfier/Data/Utils/UserSettings.cs b/Bcfier/Data/Utils/UserSettings.cs deleted file mode 100644 index 952f8a16..00000000 --- a/Bcfier/Data/Utils/UserSettings.cs +++ /dev/null @@ -1,226 +0,0 @@ -using System; -using System.Configuration; -using System.Windows; -using System.Windows.Controls; -using Bcfier.Themes; - -namespace Bcfier.Data.Utils -{ - public static class UserSettings - { - /// - /// Retrives the user setting with the specified key, if nothing is found returns an empty string - /// - /// - /// - public static string Get(string key) - { - try - { - Configuration config = GetConfig(); - - if (config == null) - return string.Empty; - - - KeyValueConfigurationElement element = config.AppSettings.Settings[key]; - if (element != null) - { - string value = element.Value; - if (!string.IsNullOrEmpty(value)) - return value; - } - else - { - config.AppSettings.Settings.Add(key, ""); - config.Save(ConfigurationSaveMode.Modified); - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return string.Empty; - } - /// - /// Sets the user setting with the specified key and value, if it doesn't exists it is created - /// - /// - /// - private static void Set(string key, string value) - { - try - { - Configuration config = GetConfig(); - if (config == null) - return; - - KeyValueConfigurationElement element = config.AppSettings.Settings[key]; - if (element != null) - element.Value = value; - else - config.AppSettings.Settings.Add(key, value); - - config.Save(ConfigurationSaveMode.Modified); - - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - /// - /// Retrives the user setting with the specified key and converts it to bool - /// - /// - /// If the key is not found or invalid return this - /// - public static bool GetBool(string key, bool defValue = false) - { - bool value = defValue; - try - { - //if it doesn't exist, use the optional default value - if(!Boolean.TryParse(Get(key), out value)) - value = defValue; - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - return value; - } - - /// - /// The configuration file used to store our settings - /// Saved in a location accessible by all modules - /// - /// - private static Configuration GetConfig() - { - string _settings = - System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "BCFier", - "settings.config"); - var configMap = new ExeConfigurationFileMap {ExeConfigFilename = _settings}; - var config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None); - - if (config == null) - MessageBox.Show("Error loading the Configuration file.", "Configuration Error", MessageBoxButton.OK, MessageBoxImage.Error); - return config; - } - - /// - /// Tries to set user controls to what they were last time the user used the app - /// - public static void LoadControlSettings(Control control) - { - try - { - if (control.GetType() == typeof(TextBox)) - { - var textbox = control as TextBox; - if (textbox == null) - return; - var value = Get(textbox.Name); - if (!string.IsNullOrEmpty(value)) - textbox.Text = value; - } - else if (control.GetType() == typeof(TextPlaceholder)) - { - var textbox = control as TextPlaceholder; - if (textbox == null) - return; - var value = Get(textbox.Name); - if (!string.IsNullOrEmpty(value)) - textbox.Text = value; - } - else if (control.GetType() == typeof(ComboBox)) - { - var combobox = control as ComboBox; - if (combobox == null) - return; - var value = Get(combobox.Name); - if (!string.IsNullOrEmpty(value)) - { - int elemIndex = 0; - int.TryParse(value, out elemIndex); - if (combobox.Items.Count > elemIndex) - combobox.SelectedIndex = elemIndex; - } - } - else if (control.GetType() == typeof(CheckBox)) - { - var checkbox = control as CheckBox; - if (checkbox == null) - return; - bool value; - if (Boolean.TryParse(Get(checkbox.Name), out value)) - checkbox.IsChecked = value; - } - else if (control.GetType() == typeof(TabControl)) - { - var tabcontrol = control as TabControl; - if (tabcontrol == null) - return; - int value; - if (int.TryParse(Get(tabcontrol.Name), out value)) - tabcontrol.SelectedIndex = value; - } - } - catch (Exception ex) - { - Console.Write(ex.Message); - } - } - /// - /// Tries to set user controls to what they were last time the user used the app - /// - public static void SaveControlSettings(Control control) - { - try - { - if (control.GetType() == typeof(TextBox)) - { - var textbox = control as TextBox; - if (textbox == null) - return; - Set(textbox.Name, textbox.Text); - } - else if (control.GetType() == typeof(TextPlaceholder)) - { - var textbox = control as TextPlaceholder; - if (textbox == null) - return; - Set(textbox.Name, textbox.Text); - } - else if (control.GetType() == typeof(ComboBox)) - { - var combobox = control as ComboBox; - if (combobox == null) - return; - var elemIndex = combobox.SelectedIndex; - if (elemIndex != -1) - Set(combobox.Name, elemIndex.ToString()); - } - else if (control.GetType() == typeof(CheckBox)) - { - var checkbox = control as CheckBox; - if (checkbox == null || !checkbox.IsChecked.HasValue) - return; - Set(checkbox.Name, checkbox.IsChecked.Value.ToString()); - } - else if (control.GetType() == typeof(TabControl)) - { - var tabcontrol = control as TabControl; - if (tabcontrol == null) - return; - Set(tabcontrol.Name, tabcontrol.SelectedIndex.ToString()); - } - } - catch (Exception ex) - { - Console.Write(ex.Message); - } - } - } -} diff --git a/Bcfier/Data/Utils/Utils.cs b/Bcfier/Data/Utils/Utils.cs deleted file mode 100644 index 5c882f1b..00000000 --- a/Bcfier/Data/Utils/Utils.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Principal; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace Bcfier.Data.Utils -{ - public static class Utils - { - public static bool IsFileLocked(string path) - { - if (!File.Exists(path)) - return false; - var file = new FileInfo(path); - FileStream stream = null; - try - { - stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); - } - catch (IOException) - { - //the file is unavailable because it is: - //still being written to - //or being processed by another thread - //or does not exist (has already been processed) - return true; - } - finally - { - if (stream != null) - stream.Close(); - } - - //file is not locked - return false; - } - /// - /// If no Username is set in settings returns the Windows username - /// - /// - public static string GetUsername() - { - string username = UserSettings.Get("BCFusername"); - - if (string.IsNullOrEmpty(username)) //EMPTY VALUE IN CONFIG - { - string s = WindowsIdentity.GetCurrent().Name; - int stop = s.IndexOf("\\"); - username = (stop > -1) ? s.Substring(stop + 1, s.Length - stop - 1) : "Unknown User"; - } - return username; - } - - /// - /// Recursively deletes safely a directory and its content - /// - /// - public static void DeleteDirectory(string target_dir) - { - try - { - if (Directory.Exists(target_dir)) - { - string[] files = Directory.GetFiles(target_dir); - string[] dirs = Directory.GetDirectories(target_dir); - foreach (string file in files) - { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); - } - - foreach (string dir in dirs) - { - DeleteDirectory(dir); - } - Directory.Delete(target_dir, false); - } - } - catch (System.Exception ex1) - { - MessageBox.Show("exception: " + ex1); - } - } - - } -} diff --git a/Bcfier/Data/ValueConverters/BoolStarConverter.cs b/Bcfier/Data/ValueConverters/BoolStarConverter.cs deleted file mode 100644 index 3f2cba4f..00000000 --- a/Bcfier/Data/ValueConverters/BoolStarConverter.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Bcfier.Data.ValueConverters -{ - /// - /// If the value is false return a *. - /// Used to append * to unsaved file names. - /// - [ValueConversion(typeof(Boolean), typeof(string))] - public class BoolStarConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return ((bool)value) ? "" : "*"; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - } - -} diff --git a/Bcfier/Data/ValueConverters/BoolVisibConverter.cs b/Bcfier/Data/ValueConverters/BoolVisibConverter.cs deleted file mode 100644 index b3f1c3b0..00000000 --- a/Bcfier/Data/ValueConverters/BoolVisibConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Data; -using System.Globalization; - -namespace Bcfier.Data.ValueConverters -{ - - /// - /// return visible if true. - /// can set second parameter to be "opposite" to reverse the functionality - /// - [ValueConversion(typeof(String), typeof(Visibility))] - public class BoolVisibConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null) - value = false; - bool c = (bool)value; - - if (parameter!=null&¶meter.ToString() == "opposite") - c = !c; - - return (c) ? Visibility.Visible : Visibility.Collapsed; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - } -} \ No newline at end of file diff --git a/Bcfier/Data/ValueConverters/DateConverter.cs b/Bcfier/Data/ValueConverters/DateConverter.cs deleted file mode 100644 index 168e307c..00000000 --- a/Bcfier/Data/ValueConverters/DateConverter.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using Bcfier.Data.Utils; - - -namespace Bcfier.Data.ValueConverters -{ - /// - /// Converts a date to relative - /// - [ValueConversion(typeof(DateTime), typeof(String))] - public class DateConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null) - return ""; - var date = new DateTime(); - if (! DateTime.TryParse(value.ToString(), out date)) - return ""; - - if (parameter!=null&¶meter.ToString() == "relative") - return RelativeDate.ToRelative(date); - else - return date.ToShortDateString() + " at " + date.ToShortTimeString(); - - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - } -} diff --git a/Bcfier/Data/ValueConverters/IntPluralConverter.cs b/Bcfier/Data/ValueConverters/IntPluralConverter.cs deleted file mode 100644 index 65df6afc..00000000 --- a/Bcfier/Data/ValueConverters/IntPluralConverter.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Text; -using System.Windows.Data; -using System.Globalization; - -namespace Bcfier.Data.ValueConverters -{ - /// - /// Returna string formatted to have a number and a plural - /// using %0% and %s% as wildcards - /// - [ValueConversion(typeof(Int16), typeof(String))] - public class IntPluralConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var count = (int)value; - var plural = (count == 1) ? "" : "s"; - - var text = ""; - if (parameter != null) - text = parameter.ToString(); - text = text.Replace("%0%", count.ToString()); - text = text.Replace("%s%", plural); - - - return text; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - } -} diff --git a/Bcfier/Data/ValueConverters/IntVisibConverter.cs b/Bcfier/Data/ValueConverters/IntVisibConverter.cs deleted file mode 100644 index 693d8ef6..00000000 --- a/Bcfier/Data/ValueConverters/IntVisibConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Data; -using System.Globalization; - -namespace Bcfier.Data.ValueConverters -{ - - /// - /// If the value is 0 or -1 returns collapsed - /// - [ValueConversion(typeof(String), typeof(Visibility))] - public class IntVisibConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var c = (int)value; - return (c == 0 || c == -1) ? Visibility.Collapsed : Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - } -} diff --git a/Bcfier/Data/ValueConverters/MultiCommandConverter.cs b/Bcfier/Data/ValueConverters/MultiCommandConverter.cs deleted file mode 100644 index 6d3ccae3..00000000 --- a/Bcfier/Data/ValueConverters/MultiCommandConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Bcfier.Data.ValueConverters -{ - /// - /// Needed to assign bultiple bindings to a command - /// - public class MultiCommandConverter : IMultiValueConverter - { - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - return values.Clone(); - } - - public object[] ConvertBack(object values, Type[] targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} - - diff --git a/Bcfier/Data/ValueConverters/PathToImageConv.cs b/Bcfier/Data/ValueConverters/PathToImageConv.cs deleted file mode 100644 index 5d9918c2..00000000 --- a/Bcfier/Data/ValueConverters/PathToImageConv.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Windows.Data; -using System.Windows.Media.Imaging; -using System.Globalization; -using Bcfier.Data.Utils; - -namespace Bcfier.Data.ValueConverters -{ - /// - /// This avoids issues when deleting an image that is loaded by the UI - /// - [ValueConversion(typeof(String), typeof(BitmapImage))] - public class PathToImageConv : IValueConverter - { - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null) - return null; - - if (!string.IsNullOrEmpty(value.ToString())) - { - return ImagingUtils.BitmapFromPath(value.ToString()); - } - - return null; - - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - - throw new NotImplementedException(); - } - - - - } -} diff --git a/Bcfier/Properties/AssemblyInfo.cs b/Bcfier/Properties/AssemblyInfo.cs deleted file mode 100755 index 3d7cbdc9..00000000 --- a/Bcfier/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bcfier")] -[assembly: AssemblyDescription("Bcfier")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("teocomi")] -[assembly: AssemblyProduct("Bcfier")] -[assembly: AssemblyCopyright("Copyright © teocomi 2017")] -[assembly: AssemblyTrademark("teocomi")] -[assembly: AssemblyCulture("")] - -[assembly: InternalsVisibleTo("Bcfier.Revit")] -[assembly: InternalsVisibleTo("Bcfier.Win")] -[assembly: InternalsVisibleTo("Bcfier.XbimXplorer")] -[assembly: InternalsVisibleTo("Bcfier.Navisworks")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - -[assembly: GuidAttribute("0d553633-80f8-490b-84d6-9d3d6ad4196d")] diff --git a/Bcfier/Properties/Resources.Designer.cs b/Bcfier/Properties/Resources.Designer.cs deleted file mode 100644 index 92ef718f..00000000 --- a/Bcfier/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bcfier.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Bcfier/Properties/Resources.resx b/Bcfier/Properties/Resources.resx deleted file mode 100644 index af7dbebb..00000000 --- a/Bcfier/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bcfier/Properties/Settings.Designer.cs b/Bcfier/Properties/Settings.Designer.cs deleted file mode 100644 index 8af53178..00000000 --- a/Bcfier/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Bcfier.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Bcfier/Properties/Settings.settings b/Bcfier/Properties/Settings.settings deleted file mode 100644 index 033d7a5e..00000000 --- a/Bcfier/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier/SampleBcfFile.xaml b/Bcfier/SampleBcfFile.xaml deleted file mode 100644 index 194cecf5..00000000 --- a/Bcfier/SampleBcfFile.xaml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - Issue - Problem - Solution - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/ButtonIcon.cs b/Bcfier/Themes/ButtonIcon.cs deleted file mode 100644 index ef03e581..00000000 --- a/Bcfier/Themes/ButtonIcon.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace Bcfier.Themes -{ - /// - /// A custom button with an icon and different settings - /// Can be Vertical - /// - public class ButtonIcon : Button - { - static ButtonIcon() - { - DefaultStyleKeyProperty.OverrideMetadata( - typeof(ButtonIcon), - new FrameworkPropertyMetadata(typeof(ButtonIcon))); - } - - public static readonly DependencyProperty IconColorProperty = DependencyProperty.Register("IconColor", typeof(Brush), typeof(ButtonIcon)); - public Brush IconColor - { - get { return (Brush)GetValue(IconColorProperty); } - set { SetValue(IconColorProperty, value); } - } - public static readonly DependencyProperty DisabledIconColorProperty = DependencyProperty.Register("DisabledIconColor", typeof(Brush), typeof(ButtonIcon)); - public Brush DisabledIconColor - { - get { return (Brush)GetValue(DisabledIconColorProperty); } - set { SetValue(DisabledIconColorProperty, value); } - } - - public static readonly DependencyProperty HighlightColorProperty = DependencyProperty.Register("HighlightColor", typeof(Brush), typeof(ButtonIcon)); - public Brush HighlightColor - { - get { return (Brush)GetValue(HighlightColorProperty); } - set { SetValue(HighlightColorProperty, value); } - } - - public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register("IconSize", typeof(int), typeof(ButtonIcon), new UIPropertyMetadata(15)); - public int IconSize - { - get { return (int)GetValue(IconSizeProperty); } - set { SetValue(IconSizeProperty, value); } - } - - public static readonly DependencyProperty IconMarginProperty = DependencyProperty.Register("IconMargin", typeof(Thickness), typeof(ButtonIcon), new UIPropertyMetadata(new Thickness(5, 0, 4, 0))); - public Thickness IconMargin - { - get { return (Thickness)GetValue(IconMarginProperty); } - set { SetValue(IconMarginProperty, value); } - } - - public static readonly DependencyProperty IconSizeVerticalProperty = DependencyProperty.Register("IconSizeVertical", typeof(int), typeof(ButtonIcon), new UIPropertyMetadata(25)); - public int IconSizeVertical - { - get { return (int)GetValue(IconSizeVerticalProperty); } - set { SetValue(IconSizeVerticalProperty, value); } - } - - public static readonly DependencyProperty IconMarginVerticalProperty = DependencyProperty.Register("IconMarginVertical", typeof(Thickness), typeof(ButtonIcon), new UIPropertyMetadata(new Thickness(5))); - public Thickness IconMarginVertical - { - get { return (Thickness)GetValue(IconMarginVerticalProperty); } - set { SetValue(IconMarginVerticalProperty, value); } - } - - public static readonly DependencyProperty IconPathProperty = DependencyProperty.Register("IconPath", typeof(Geometry), typeof(ButtonIcon)); - public System.Windows.Media.Geometry IconPath - { - get { return (Geometry)GetValue(IconPathProperty); } - set { SetValue(IconPathProperty, value); } - } - - public static readonly DependencyProperty IsVerticalProperty = DependencyProperty.Register( - "IsVertical", - typeof(Boolean), - typeof(ButtonIcon), - new PropertyMetadata(false)); - - public Boolean IsVertical - { - get { return (Boolean)GetValue(IsVerticalProperty); } - set { SetValue(IsVerticalProperty, value); } - } - - } -} diff --git a/Bcfier/Themes/ButtonStyles.xaml b/Bcfier/Themes/ButtonStyles.xaml deleted file mode 100644 index 350661c2..00000000 --- a/Bcfier/Themes/ButtonStyles.xaml +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/Colors.xaml b/Bcfier/Themes/Colors.xaml deleted file mode 100644 index 2cceb6c2..00000000 --- a/Bcfier/Themes/Colors.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - #4DBFF5 - #34A6DC - #14324A - #0F2636 - #F5F6FA - #E0E7ED - \ No newline at end of file diff --git a/Bcfier/Themes/Generic.xaml b/Bcfier/Themes/Generic.xaml deleted file mode 100644 index 4e43fcc2..00000000 --- a/Bcfier/Themes/Generic.xaml +++ /dev/null @@ -1,208 +0,0 @@ - - - #FFE8EDF9 - #FFC5CBF9 - #FF888888 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/Icons.xaml b/Bcfier/Themes/Icons.xaml deleted file mode 100644 index 843ab95d..00000000 --- a/Bcfier/Themes/Icons.xaml +++ /dev/null @@ -1,86 +0,0 @@ - - M43.8,0H0v100h75V31.2L43.8,0z M37.2,37.5v-25l25,25H37.2z - M91,100.3h9.1v-82L81.9,0L18.2,0L0,0l0,100.3H91z M18.2,9.1h27.3v27.3h18.2V9.1h9.1v36.5H18.2V9.1z - M0.5,86.5h72.5l27.2-53.2H27.6L0.5,86.5z M-0.2,73.5l23.4-47.1l49.7-0.1V10.6H35.5V0.8H9.5l-9.1,9.8L-0.2,73.5z - M-5.824,12.125h-43.799v21.629h13.35l34.13,34.129v44.241h27.521v-68.8L-5.824,12.125z M-12.423,49.625v-25l25,25H-12.423zM-49.623,38.25h-32.5v100h75v-16.125V69.45l-31.201-31.2H-49.623z M-44.923,75.75v-25l25,25H-44.923z - F1 M 37.6289,-0.000976563L 49.6289,-0.000976563L 52.8506,10.8311C 55.3838,11.5439 57.7979,12.542 60.0557,13.79L 70.0654,8.37012L 78.5518,16.8545L 73.1934,26.749C 74.4844,29.0117 75.5234,31.4365 76.2725,33.9863L 87.251,37.252L 87.251,49.252L 76.4746,52.457C 75.7588,55.1113 74.7295,57.6377 73.4297,59.9932L 78.8838,70.0645L 70.3994,78.5518L 60.4404,73.1582C 58.0811,74.5029 55.5439,75.5732 52.875,76.3252L 49.624,87.2549L 37.624,87.2549L 34.373,76.3232C 31.7061,75.5713 29.1729,74.501 26.8145,73.1572L 16.8574,78.5488L 8.37207,70.0635L 13.8262,59.9912C 12.5264,57.6357 11.498,55.1113 10.7822,52.458L 0,49.251L 0,37.251L 10.9854,33.9834C 11.7334,31.4365 12.7715,29.0137 14.0615,26.7529L 8.70313,16.8564L 17.1885,8.37012L 27.1982,13.791C 29.4561,12.542 31.8721,11.543 34.4072,10.8311L 37.6289,-0.000976563 Z M 43.9824,59.5264C 52.9834,59.5264 60.2803,52.2275 60.2803,43.2275C 60.2803,34.2266 52.9834,26.9277 43.9824,26.9277C 34.9824,26.9277 27.6826,34.2266 27.6826,43.2275C 27.6826,52.2275 34.9824,59.5264 43.9824,59.5264 Z - - M50,100C22.4,100,0,77.6,0,50S22.4,0,50,0s50,22.4,50,50S77.6,100,50,100z M24.4,55.7h19.2l0,0H56l0,0h19.2 - V43.5H56l0,0H43.6l0,0H24.4V55.7z - - - M50,100C22.4,100,0,77.6,0,50S22.4,0,50,0s50,22.4,50,50S77.6,100,50,100z M24.4,55.7h19.2V75H56V55.7h19.2 - V43.5H56V24.2H43.6v19.2H24.4V55.7z - - - M444.3,318.2c-34.4,0-62.4,28-62.4,62.4c0,34.4,28,62.4,62.4,62.4s62.4-28,62.4-62.4 - C506.7,346.2,478.7,318.2,444.3,318.2z M472.2,386.1h-28l20.5,26.3h-12.3v17.8H436v-17.8h-12.3l20.5-26.3h-38.7 - c-6.2,0-11.3-5.1-11.3-11.3c0-5.3,3.6-9.7,8.5-10.9c2.2-5.5,7.2-9.4,13.1-10.1c0.6-12.7,11.1-22.8,24-22.8c9.4,0,17.8,5.5,21.7,13.8 - c3.2-1.8,6.8-2.7,10.5-2.7c12.2,0,22,9.9,22,22S484.4,386.1,472.2,386.1z - - - M421.6,235.1c-34.4,0-62.4,28-62.4,62.4c0,34.4,28,62.4,62.4,62.4c34.4,0,62.4-28,62.4-62.4 - C484,263.1,456,235.1,421.6,235.1z M449.5,303.1h-19.7v17.8h12.3l-20.5,26.3L401,320.9h12.3v-17.8h-30.5c-6.2,0-11.3-5.1-11.3-11.3 - c0-5.3,3.6-9.7,8.5-10.9c2.2-5.5,7.2-9.4,13.1-10.1c0.6-12.7,11.1-22.8,24-22.8c9.4,0,17.8,5.5,21.7,13.8c3.2-1.8,6.8-2.7,10.5-2.7 - c12.2,0,22,9.9,22,22C471.6,293.2,461.7,303.1,449.5,303.1z - - M86,32L59,45.5L59,32L14,32L14,68L59,68L59,54.5L86,68 - M8.016,4.016h84.453c1.665,0,3.016,1.351,3.016,3.016v18.097 c0,1.666-1.351,3.016-3.016,3.016H8.016C6.349,28.146,5,26.795,5,25.129V7.032C5,5.367,6.349,4.016,8.016,4.016zM8.016,37.194h84.453c1.665,0,3.016,1.349,3.016,3.016v18.097 c0,1.667-1.351,3.016-3.016,3.016H8.016C6.349,61.322,5,59.974,5,58.307V40.21C5,38.543,6.349,37.194,8.016,37.194zM8.016,70.371h84.453c1.665,0,3.016,1.349,3.016,3.016v18.098 c0,1.667-1.351,3.016-3.016,3.016H8.016C6.349,94.5,5,93.151,5,91.484V73.387C5,71.72,6.349,70.371,8.016,70.371z - - M50.6,71.3l13.6-13.6c1.2-1.2,1.2-3,0-4.2c-1.2-1.2-3-1.2-4.2,0L46.5,67.1 - L32.9,53.5L46.5,40c1.2-1.2,1.2-3,0-4.2c-1.2-1.2-3-1.2-4.2,0L28.7,49.4L24,44.7L15.7,53c-7.6,7.6-8.5,19.3-2.8,27.9L0,93.7l6.3,6.3 - l12.8-12.8c8.6,5.7,20.3,4.8,27.9-2.8l8.4-8.4C55.3,76,50.6,71.3,50.6,71.3zM76,55.3l8.4-8.4c7.6-7.6,8.5-19.3,2.8-27.9 - L100,6.3L93.7,0L80.9,12.8C72.3,7.1,60.6,8.1,53,15.7L44.7,24C75.3,54.7,44.9,24.3,76,55.3z - - - M86,18.7L78.1,27l0.2,0c-6.6-7.9-16.5-13-27.7-13c-20,0-36.1,16.1-36.1,36c0,19.9,16.2,36,36.2,36 - c15.5,0,28.7-9.7,33.8-23.3l-13.3-5.5c-3,8.4-11.1,14.5-20.5,14.5c-12,0-21.8-9.7-21.8-21.7c0-12,9.8-21.7,21.8-21.7 - c7.2,0,13.6,3.5,17.5,8.9l-8.7,8.1l26.5,0V18.7z - - M86,15L78.5,15L62.1,15L69.6,22.3L54.9,37L63.8,45.9L78.5,31.1L86,38.9M64,73L27,73L27,37L45.7,37L60.3,22L14,22L14,86L77,86L77,40.1L64,55.4 - F1 M 40.972,77.2199C 39.5052,75.4609 40.3575,72.5611 42.8998,72.5611L 52.8718,72.5611L 52.8718,29.3802C 52.8718,27.8918 54.1134,26.6503 55.6016,26.6503L 77.7318,26.6503C 79.22,26.6503 80.461,27.8918 80.461,29.3802L 80.461,72.5611L 90.4336,72.5611C 92.9765,72.5611 93.8281,75.4609 92.362,77.2199L 68.5964,105.772C 68.0156,106.471 67.3281,106.725 66.6667,106.68C 66.0052,106.725 65.3216,106.471 64.7376,105.772L 40.972,77.2199 Z M 66.6667,133.333C 29.8483,133.333 0,103.486 0,66.6666C 0,29.8476 29.8483,-3.05176e-005 66.6667,-3.05176e-005C 103.484,-3.05176e-005 133.333,29.8476 133.333,66.6666C 133.333,103.486 103.484,133.333 66.6667,133.333 Z M 66.6667,10.6667C 35.7403,10.6667 10.6667,35.7389 10.6667,66.6666C 10.6667,97.5937 35.7403,122.667 66.6667,122.667C 97.5937,122.667 122.667,97.5937 122.667,66.6666C 122.667,35.7389 97.5937,10.6667 66.6667,10.6667 Z - M87.7,21.3L69.2,2.8L45,27L20.8,2.8L2.3,21.3L26.5,45.5L2.3,69.7L20.8,88.2L45,64L69.2,88.2L87.7,69.7L63.5,45.5z - M80.452,62.66c1.529-3.789,2.392-7.922,2.392-12.259c0-4.226-0.828-8.253-2.287-11.963c1.322-0.274,2.407-0.878,3.225-1.826 c1.821-2.111,1.574-5.091,1.566-5.179c-0.271-4.812-3-9.467-7.679-13.109c-3.806-2.959-8.436-4.812-11.603-4.653 c-4.566,0.26-6.729,3.275-7.378,5.157c-2.743-0.745-5.614-1.177-8.593-1.177c-3.151,0-6.189,0.47-9.072,1.302 c-0.86-1.871-3.021-4.366-7.149-4.598c-5.997-0.326-18.679,7.092-19.282,17.723c-0.012,0.126-0.258,3.109,1.565,5.22 c0.818,0.948,1.907,1.55,3.228,1.823c-1.294,3.521-2.037,7.309-2.037,11.279c0,4.08,0.78,7.972,2.143,11.572 c-1.368,0.263-2.495,0.868-3.333,1.841c-1.823,2.11-1.577,5.093-1.568,5.181c0.592,10.433,12.655,17.772,18.87,17.772 c0.141,0,0.28-0.003,0.415-0.013c4.326-0.244,6.508-2.978,7.279-4.868c2.846,0.808,5.837,1.27,8.943,1.27 c2.944,0,5.785-0.424,8.498-1.155c0.524,1.846,2.677,5.168,7.473,5.438c0.135,0.01,0.274,0.013,0.419,0.013 c3.122,0,7.545-1.833,11.184-4.667c4.679-3.641,7.407-8.295,7.677-13.068c0.01-0.125,0.259-3.107-1.566-5.218 C82.941,63.525,81.816,62.922,80.452,62.66z M80.362,55.666H64.899c2.249-5.911,0-10.373,0-10.373h15.463 C80.362,45.293,81.734,50.264,80.362,55.666z M66.196,15.975c2.087-0.117,6.155,1.133,10.056,4.17 c2.402,1.868,6.479,5.836,6.797,11.454c0.002,0.021,0.162,2.157-1.021,3.519c-0.568,0.654-1.396,0.994-2.444,1.114 c-3.746-7.783-10.46-13.842-18.695-16.72C61.218,18.661,62.473,16.186,66.196,15.975z M50.096,63.852 c-7.425,0-13.444-6.021-13.444-13.45c0-7.425,6.02-13.443,13.444-13.443c7.426,0,13.446,6.018,13.446,13.443 C63.542,57.831,57.521,63.852,50.096,63.852z M44.91,20.126c0,0,4.968-1.367,10.372,0v15.463c-5.909-2.245-10.372,0-10.372,0V20.126 z M17.911,35.802c-1.185-1.361-1.025-3.499-1.02-3.555c0.541-9.528,12.131-15.912,16.854-15.589 c3.131,0.176,4.508,1.954,5.068,3.032c-8.243,3.032-14.921,9.263-18.526,17.209C19.275,36.771,18.466,36.439,17.911,35.802z M19.779,45.291h15.463c-2.246,5.906,0,10.37,0,10.37H19.779C19.779,55.661,18.411,50.693,19.779,45.291z M33.744,84.456 c-4.721,0.286-16.311-6.062-16.857-15.628c-0.001-0.022-0.157-2.15,1.015-3.51c0.583-0.673,1.429-1.024,2.517-1.135 c3.655,7.856,10.319,14.007,18.526,16.982C38.483,82.186,37.138,84.261,33.744,84.456z M55.284,81.009c0,0-4.97,1.369-10.373,0 V65.548c5.907,2.242,10.373,0,10.373,0V81.009z M83.046,69.549c-0.314,5.581-4.392,9.55-6.794,11.418 c-3.903,3.037-7.976,4.274-10.056,4.172c-4.29-0.244-5.312-3.486-5.402-3.806c8.178-2.831,14.869-8.799,18.655-16.479 c1.123,0.098,1.983,0.457,2.579,1.14C83.211,67.356,83.051,69.491,83.046,69.549z - - M497.617,278.363c0.01-12.373-1.448-24.409-3.764-36.179c-1.184-6.028-2.693-11.934-4.438-17.758 - c-0.112-0.367-0.214-0.734-0.326-1.102c-1.733-5.661-3.733-11.21-5.978-16.667c-0.193-0.469-0.397-0.938-0.591-1.407 - c-2.275-5.417-4.764-10.72-7.528-15.922c-0.203-0.388-0.428-0.765-0.632-1.143c-2.856-5.293-5.896-10.485-9.231-15.535 - c-0.01-0.02-0.03-0.041-0.051-0.071c-13.505-20.44-30.763-38.699-51.01-54.09c-0.775-0.592-1.489-1.224-2.275-1.806 - c-3.661-2.713-7.507-5.222-11.342-7.752c-2.122-1.397-4.202-2.835-6.375-4.172c-3.438-2.101-6.977-4.049-10.537-5.998 - c-2.794-1.54-5.6-3.06-8.466-4.498c-3.346-1.673-6.763-3.233-10.21-4.773c-3.284-1.469-6.609-2.866-9.976-4.203 - c-3.305-1.306-6.62-2.55-10.006-3.733c-3.744-1.305-7.538-2.489-11.363-3.641c-3.223-0.959-6.437-1.928-9.721-2.764 - c-4.232-1.091-8.537-2-12.862-2.897c-3.06-0.632-6.089-1.316-9.19-1.846c-4.937-0.836-9.976-1.428-15.014-1.999 - c-2.622-0.296-5.202-0.714-7.854-0.938c-7.752-0.653-15.586-1.041-23.532-1.041c-133.803,0-242.27,94.88-242.27,211.936 - c0,46.277,17.146,88.954,45.92,123.818l-41.239,95.258C61.935,485.403,99.562,473,132.08,460.586 - c36.148,18.758,78.193,29.713,123.267,29.713C389.15,490.299,497.617,395.408,497.617,278.363z - M597.944,388.728c0-52.245-28.07-98.655-71.624-128.632c0.51,6.048,1.04,12.087,1.04,18.248 - c0,121.268-101.174,221.677-232.407,238.803c31.875,22.032,72.052,35.292,115.841,35.292c34.813,0,67.3-8.466,95.217-22.95 - c25.112,9.588,54.183,19.166,88.302,28.468l-31.854-73.572C584.694,457.444,597.944,424.479,597.944,388.728z - - - M313.362,331.942c-38.256,0-69.254,31.004-69.254,69.254c0,38.25,30.992,69.254,69.254,69.254 - c38.25,0,69.26-31.004,69.26-69.254C382.622,362.946,351.612,331.942,313.362,331.942z - M446.681,279.72h-46.678c-2.797-18.36-14.425-24.479-28.366-24.479H240.944c-13.929,0-25.569,6.12-28.354,24.479h-45.062 - c-19.394,0-39.009,14.566-39.009,33.954v175.729c0,19.4,19.615,35.116,39.009,35.116h279.152c19.394,0,30.68-15.716,30.68-35.116 - V313.674C477.36,294.286,466.074,279.72,446.681,279.72z M176.819,345.002c-11.444,0-20.716-9.278-20.716-20.716 - c0-11.457,9.271-20.722,20.716-20.722c11.445,0,20.723,9.272,20.723,20.722C197.542,335.724,188.264,345.002,176.819,345.002z - M313.351,489.177c-48.587,0-87.969-37.999-87.969-86.579c0.006-45.729,34.859-86.158,79.462-86.158h17.039 - c44.59,0,79.449,40.429,79.449,86.151C401.331,451.178,361.943,489.177,313.351,489.177z - - M94.5,50.474c0-1.465-0.899-2.376-2.162-3.042c-0.076-0.048-85.45-37.288-85.45-37.288C6.669,10.045,6.438,10,6.204,10 c-0.327,0-0.65,0.089-0.933,0.272C4.789,10.582,4.5,11.119,4.5,11.686v33.773c0,0.91,0.721,1.651,1.635,1.686L90.627,50.5 L6.135,53.849C5.221,53.887,4.5,54.628,4.5,55.539v33.773c0,0.565,0.289,1.102,0.771,1.415C5.553,90.906,5.877,91,6.204,91 c0.231,0,0.463-0.047,0.684-0.146l84.519-36.855C93.047,53.377,94.5,52.249,94.5,50.474z - - M358.934,375.853c-10.606,10.643-20.91,21.002-31.239,31.335 - c-7.427,7.431-15.184,8.651-23.882,2.719c-4.314-2.942-8.258-6.955-11.195-11.28c-5.598-8.243-4.444-16.238,2.577-23.375 - c9.461-9.616,19.046-19.109,28.618-28.615c0.969-0.963,2.211-1.65,3.526-2.611c-9.295-9.266-17.99-17.864-26.568-26.578 - c-1.107-1.125-1.607-2.848-2.388-4.294c1.489-0.667,2.937-1.793,4.474-1.931c16.027-1.439,32.069-2.714,48.105-4.047 - c13.923-1.158,27.852-2.254,41.764-3.533c6.142-0.564,6.724-0.102,6.226,5.957c-2.105,25.614-4.152,51.234-6.245,76.85 - c-0.396,4.849-0.807,9.701-1.421,14.525c-0.151,1.189-0.903,2.911-1.791,3.226c-0.874,0.311-2.544-0.576-3.397-1.414 - c-8.107-7.966-16.113-16.037-24.154-24.07C361.071,377.845,360.158,377.016,358.934,375.853zM219.328,451.615c5.398-5.422,10.494-10.549,15.599-15.664 - c5.648-5.659,11.29-11.325,16.966-16.957c4.861-4.823,10.723-6.539,17.151-4.226c9.431,3.395,16.062,9.962,19.235,19.555 - c2.168,6.553,0.178,12.268-4.626,17.074c-9.715,9.72-19.436,19.434-29.148,29.156c-0.956,0.957-1.863,1.963-2.987,3.152 - c8.432,8.426,16.719,16.709,25.006,24.992c0.795,0.795,1.648,1.541,2.369,2.399c2.145,2.554,1.536,4.463-1.834,4.833 - c-7.439,0.815-14.908,1.367-22.367,1.995c-20.141,1.694-40.283,3.372-60.425,5.057c-3.605,0.302-7.207,0.664-10.817,0.894 - c-3.927,0.25-4.681-0.478-4.36-4.507c1.009-12.688,2.106-25.368,3.17-38.052c1.418-16.91,2.777-33.827,4.32-50.727 - c0.234-2.563,1.33-5.047,2.026-7.567c2.17,1.423,4.637,2.542,6.46,4.32C203.114,435.189,210.977,443.225,219.328,451.615z - - \ No newline at end of file diff --git a/Bcfier/Themes/IssueListStyle.xaml b/Bcfier/Themes/IssueListStyle.xaml deleted file mode 100644 index cd14ff2d..00000000 --- a/Bcfier/Themes/IssueListStyle.xaml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/IssueListStyle.xaml.cs b/Bcfier/Themes/IssueListStyle.xaml.cs deleted file mode 100644 index daa53791..00000000 --- a/Bcfier/Themes/IssueListStyle.xaml.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Windows.Controls; -using System.Windows.Input; - -namespace Bcfier.Themes -{ - public partial class IssueListStyle - { - protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e) - { - var item = (ListViewItem)sender; - item.IsSelected = true; - } - } -} diff --git a/Bcfier/Themes/LabelSelectable.cs b/Bcfier/Themes/LabelSelectable.cs deleted file mode 100644 index 02801030..00000000 --- a/Bcfier/Themes/LabelSelectable.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace Bcfier.Themes -{ - /// - /// A control that looks like a label but can be selected - /// More code in generic.xaml - /// - public class LabelSelectable : TextBox - { - static LabelSelectable() - { - DefaultStyleKeyProperty.OverrideMetadata( - typeof(LabelSelectable), - new FrameworkPropertyMetadata(typeof(LabelSelectable))); - } - } -} diff --git a/Bcfier/Themes/ScrollViewer.xaml b/Bcfier/Themes/ScrollViewer.xaml deleted file mode 100644 index 82d709ce..00000000 --- a/Bcfier/Themes/ScrollViewer.xaml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/TextPlaceholder.cs b/Bcfier/Themes/TextPlaceholder.cs deleted file mode 100644 index 7608ee85..00000000 --- a/Bcfier/Themes/TextPlaceholder.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - - -namespace Bcfier.Themes -{ - /// - /// A TextBox with a placeholder - /// more code in generic.xaml - /// - public class TextPlaceholder : TextBox - { - - public static DependencyProperty PlaceholderProperty = - DependencyProperty.Register( - "Placeholder", - typeof(string), - typeof(TextPlaceholder)); - - public static DependencyProperty PlaceholderColorProperty = - DependencyProperty.Register( - "PlaceholderColor", - typeof(Brush), - typeof(TextPlaceholder)); - - - private static DependencyPropertyKey HasTextPropertyKey = - DependencyProperty.RegisterReadOnly( - "HasText", - typeof(bool), - typeof(TextPlaceholder), - new PropertyMetadata()); - public static DependencyProperty HasTextProperty = HasTextPropertyKey.DependencyProperty; - - - static TextPlaceholder() - { - DefaultStyleKeyProperty.OverrideMetadata( - typeof(TextPlaceholder), - new FrameworkPropertyMetadata(typeof(TextPlaceholder))); - } - - - - protected override void OnTextChanged(TextChangedEventArgs e) - { - base.OnTextChanged(e); - - HasText = Text.Length != 0; - - } - - - public string Placeholder - { - get { return (string)GetValue(PlaceholderProperty); } - set { SetValue(PlaceholderProperty, value); } - } - - public Brush PlaceholderColor - { - get { return (Brush)GetValue(PlaceholderColorProperty); } - set { SetValue(PlaceholderColorProperty, value); } - } - - - - public bool HasText - { - get { return (bool)GetValue(HasTextProperty); } - private set { SetValue(HasTextPropertyKey, value); } - } - - } -} diff --git a/Bcfier/Themes/ViewCommentDataTemplate.cs b/Bcfier/Themes/ViewCommentDataTemplate.cs deleted file mode 100644 index df2cfd97..00000000 --- a/Bcfier/Themes/ViewCommentDataTemplate.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls.Primitives; -using System.Windows.Input; - -namespace Bcfier.Themes -{ - public partial class ViewCommentDataTemplate : ResourceDictionary - { - public ViewCommentDataTemplate() - { - InitializeComponent(); - } - - private void UIElement_OnKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - { - //AddCommButton.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent)); - } - } - } -} diff --git a/Bcfier/Themes/ViewCommentDataTemplate.xaml b/Bcfier/Themes/ViewCommentDataTemplate.xaml deleted file mode 100644 index e7fdd03a..00000000 --- a/Bcfier/Themes/ViewCommentDataTemplate.xaml +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/ViewCommentListStyle.xaml b/Bcfier/Themes/ViewCommentListStyle.xaml deleted file mode 100644 index db0160f9..00000000 --- a/Bcfier/Themes/ViewCommentListStyle.xaml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Bcfier/Themes/VisibilityAnimations.xaml b/Bcfier/Themes/VisibilityAnimations.xaml deleted file mode 100644 index 01fe3cff..00000000 --- a/Bcfier/Themes/VisibilityAnimations.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bcfier/UserControls/AddView.xaml b/Bcfier/UserControls/AddView.xaml deleted file mode 100644 index fc61ae1f..00000000 --- a/Bcfier/UserControls/AddView.xaml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/src/ipa-bcfier-ui/src/app/app.component.scss b/src/ipa-bcfier-ui/src/app/app.component.scss new file mode 100644 index 00000000..0903d697 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/app.component.scss @@ -0,0 +1,25 @@ +bcfier-top-menu { + padding-left: 20px; + width: 100%; +} + +.logo { + height: 48px; + margin-bottom: 1rem; +} + +.file-close-button { + margin-left: 10px; +} + +mat-tab-group { + height: calc(100% - 64px); + min-height: calc(100% - 64px); + min-width: 100%; + width: 100%; + margin: 0px; +} + +::ng-deep .mat-mdc-tab-header { + margin: 0 0 1rem; +} diff --git a/src/ipa-bcfier-ui/src/app/app.component.spec.ts b/src/ipa-bcfier-ui/src/app/app.component.spec.ts new file mode 100644 index 00000000..69f02cd6 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/app.component.spec.ts @@ -0,0 +1,29 @@ +import { TestBed } from '@angular/core/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AppComponent], + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have the 'ipa-bcfier-ui' title`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('ipa-bcfier-ui'); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.nativeElement as HTMLElement; + expect(compiled.querySelector('h1')?.textContent).toContain('Hello, ipa-bcfier-ui'); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/app.component.ts b/src/ipa-bcfier-ui/src/app/app.component.ts new file mode 100644 index 00000000..fa544d38 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/app.component.ts @@ -0,0 +1,223 @@ +import { + BcfFile, + BcfFileWrapper, + ProjectsClient, +} from './generated-client/generated-client'; +import { Component, OnDestroy, ViewChild } from '@angular/core'; +import { MatTabGroup, MatTabsModule } from '@angular/material/tabs'; +import { + Observable, + Subject, + filter, + map, + of, + switchMap, + take, + takeUntil, + tap, +} from 'rxjs'; + +import { AppConfigService } from './services/AppConfigService'; +import { BackendService } from './services/BackendService'; +import { BcfFileAutomaticallySaveService } from './services/bcf-file-automaticaly-save.service'; +import { BcfFileComponent } from './components/bcf-file/bcf-file.component'; +import { BcfFilesMessengerService } from './services/bcf-files-messenger.service'; +import { BcfierHubConnectorService } from './services/connectors/bcfier-hub-connector.service'; +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { NotificationsService } from './services/notifications.service'; +import { SelectedProjectMessengerService } from './services/selected-project-messenger.service'; +import { TopMenuComponent } from './components/top-menu/top-menu.component'; +import { version } from './version'; + +@Component({ + selector: 'bcfier-root', + standalone: true, + imports: [ + MatToolbarModule, + MatTabsModule, + TopMenuComponent, + CommonModule, + BcfFileComponent, + MatIconModule, + MatButtonModule, + ], + templateUrl: './app.component.html', + styleUrl: './app.component.scss', +}) +export class AppComponent implements OnDestroy { + bcfFiles: Observable; + @ViewChild(MatTabGroup) tabGroup: MatTabGroup | undefined; + private destroyed$ = new Subject(); + constructor( + private bcfFilesMessengerService: BcfFilesMessengerService, + private backendService: BackendService, + private notificationsService: NotificationsService, + private bcfFileAutomaticallySaveService: BcfFileAutomaticallySaveService, + private bcfierHubConnectorService: BcfierHubConnectorService, // We want to initialize it so it's listening to SignalR messages + appConfigService: AppConfigService, + projectsClient: ProjectsClient, + selectedProjectMessengerService: SelectedProjectMessengerService + ) { + if ( + appConfigService.getFrontendConfig().isConnectedToRevit && + !!appConfigService.getFrontendConfig().revitProjectPath + ) { + projectsClient + .getAllProjects( + null, + appConfigService.getFrontendConfig().revitProjectPath + ) + .subscribe((projects) => { + if (projects?.data?.length && projects.data.length > 0) { + const selectedProject = projects.data[0]; + selectedProjectMessengerService.setSelectedProject(selectedProject); + } + }); + } + + const cadPluginVersion = + appConfigService.getFrontendConfig().cadPluginVersion; + if (!!cadPluginVersion && version.version !== cadPluginVersion) { + this.notificationsService.info( + `The BCFier version (${version.version}) is different from the CAD plugin version (${cadPluginVersion}).` + ); + } + + this.changeSelectedTabIndex(0); + this.bcfFiles = bcfFilesMessengerService.bcfFiles; + this.bcfFilesMessengerService.bcfFileSaveAsRequested + .pipe( + takeUntil(this.destroyed$), + switchMap(() => this.bcfFiles.pipe(take(1))), + filter( + (bcfFiles) => + !!this.tabGroup && + this.tabGroup.selectedIndex != null && + bcfFiles.length > this.tabGroup.selectedIndex && + !!bcfFiles.length + ), + map((bcfFiles) => { + const selectedIndex = this.tabGroup?.selectedIndex as number; + const selectedBcfFile = bcfFiles[selectedIndex]; + return selectedBcfFile; + }), + filter((selectedBcfFile) => !!selectedBcfFile), + switchMap((selectedBcfFile) => { + return this.backendService.exportBcfFile(selectedBcfFile).pipe( + tap((response) => { + if (response && response.fileName) { + selectedBcfFile.fileName = response.fileName; + if (selectedBcfFile.bcfFile) { + selectedBcfFile.bcfFile.fileName = response.fileName.replace( + /^.*[\\/]/, + '' + ); + } + } + }) + ); + }) + ) + .subscribe({ + next: () => { + this.notificationsService.success('BCF file saved successfully.'); + }, + error: (error) => { + console.error('Error exporting BCF file:', error); + this.notificationsService.error('Failed to save BCF file.'); + }, + }); + + this.bcfFileAutomaticallySaveService.bcfFileSaveAutomaticallyRequested + .pipe( + takeUntil(this.destroyed$), + switchMap(() => this.bcfFiles.pipe(take(1))), + filter( + (bcfFiles) => + !!this.tabGroup && + this.tabGroup.selectedIndex != null && + bcfFiles.length > this.tabGroup.selectedIndex && + !!bcfFiles.length + ), + map((bcfFiles) => { + const selectedIndex = this.tabGroup?.selectedIndex as number; + const selectedBcfFile = bcfFiles[selectedIndex]; + return selectedBcfFile; + }), + filter((selectedBcfFile) => !!selectedBcfFile), + switchMap((selectedBcfFile) => { + if (selectedBcfFile.fileName) { + return this.backendService.saveBcfFile(selectedBcfFile); + } else { + return of(false); + } + }) + ) + .subscribe({ + next: (value?) => { + if (typeof value === 'boolean' && !value) { + this.notificationsService.info( + 'Please use "Save As" to save the BCF file.' + ); + } else { + this.notificationsService.success('BCF file saved successfully.'); + } + }, + error: (error) => { + console.error('Error exporting BCF file:', error); + this.notificationsService.error('Failed to save BCF file.'); + }, + }); + + this.bcfFilesMessengerService.bcfFileSelected + .pipe(takeUntil(this.destroyed$)) + .subscribe((selectedBcfFile) => { + this.bcfFilesMessengerService.bcfFiles + .pipe(take(1)) + .subscribe((bcfFiles) => { + if ( + bcfFiles && + bcfFiles.length && + selectedBcfFile && + selectedBcfFile.bcfFile + ) { + this.updateTabIndex( + selectedBcfFile.bcfFile, + bcfFiles.map((f) => f.bcfFile!) + ); + } + }); + }); + } + + updateTabIndex(bcfFile: BcfFile, bcfFiles: BcfFile[]): void { + if (this.tabGroup) { + this.tabGroup.selectedIndex = bcfFiles.indexOf(bcfFile); + } + } + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + closeBcfFile(bcfFile: BcfFile): void { + this.bcfFilesMessengerService.closeBcfFile(bcfFile); + if (this.tabGroup && this.tabGroup.selectedIndex !== null) { + this.changeSelectedTabIndex(this.tabGroup.selectedIndex); + } + } + + changeSelectedTabIndex(index: number): void { + this.bcfFilesMessengerService.bcfFiles + .pipe(take(1)) + .subscribe((bcfFiles) => { + if (bcfFiles.length && bcfFiles[index] !== undefined) { + this.bcfFilesMessengerService.setBcfFileSelected(bcfFiles[index]); + } + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/app.config.ts b/src/ipa-bcfier-ui/src/app/app.config.ts new file mode 100644 index 00000000..34f6d475 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/app.config.ts @@ -0,0 +1,42 @@ +import { + MAT_DATE_LOCALE, + provideNativeDateAdapter, +} from '@angular/material/core'; + +import { AppConfigService } from './services/AppConfigService'; +import { ApplicationConfig } from '@angular/core'; +import { BackendService } from './services/BackendService'; +import { IMAGE_CONFIG } from '@angular/common'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { provideHttpClient } from '@angular/common/http'; +import { provideRouter } from '@angular/router'; +import { provideToastr } from 'ngx-toastr'; +import { routes } from './app.routes'; + +const frontendConfigService = new AppConfigService(); + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + provideAnimationsAsync(), + provideHttpClient(), + { + provide: BackendService, + useClass: BackendService, + }, + { + provide: IMAGE_CONFIG, + useValue: { + disableImageSizeWarning: true, + disableImageLazyLoadWarning: true, + }, + }, + provideToastr({ + positionClass: 'toast-bottom-right', + preventDuplicates: true, + closeButton: true, + }), + { provide: MAT_DATE_LOCALE, useValue: 'en-UK' }, + provideNativeDateAdapter(), + ], +}; diff --git a/src/ipa-bcfier-ui/src/app/app.routes.ts b/src/ipa-bcfier-ui/src/app/app.routes.ts new file mode 100644 index 00000000..dc39edb5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/app.routes.ts @@ -0,0 +1,3 @@ +import { Routes } from '@angular/router'; + +export const routes: Routes = []; diff --git a/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.html b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.html new file mode 100644 index 00000000..b4fbb615 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.html @@ -0,0 +1,25 @@ +

Add Viewpoint

+ +

You can create a new viewpoint without geometry here.

+ + Drop an Image File + + + @if (fileCtrl.value) { + + {{ fileCtrl.value.name }} + + + } + + image + +
+ + + + diff --git a/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.scss b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.scss new file mode 100644 index 00000000..3e2ef812 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.scss @@ -0,0 +1,3 @@ +.upload-form { + width: 100%; +} diff --git a/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.spec.ts new file mode 100644 index 00000000..3c6c45ff --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddSnapshotViewpointComponent } from './add-snapshot-viewpoint.component'; + +describe('AddSnapshotViewpointComponent', () => { + let component: AddSnapshotViewpointComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddSnapshotViewpointComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddSnapshotViewpointComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.ts b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.ts new file mode 100644 index 00000000..e2e7a184 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-snapshot-viewpoint/add-snapshot-viewpoint.component.ts @@ -0,0 +1,90 @@ +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; + +import { BcfViewpoint } from '../../generated-client/generated-client'; +import { Component } from '@angular/core'; +import { DropzoneCdkModule } from '@ngx-dropzone/cdk'; +import { DropzoneMaterialModule } from '@ngx-dropzone/material'; +import { MatButtonModule } from '@angular/material/button'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { getNewRandomGuid } from '../../functions/uuid'; + +@Component({ + selector: 'bcfier-add-snapshot-viewpoint', + standalone: true, + imports: [ + MatInputModule, + FormsModule, + ReactiveFormsModule, + MatChipsModule, + MatDialogModule, + MatIconModule, + MatButtonModule, + DropzoneCdkModule, + DropzoneMaterialModule, + ], + templateUrl: './add-snapshot-viewpoint.component.html', + styleUrl: './add-snapshot-viewpoint.component.scss', +}) +export class AddSnapshotViewpointComponent { + constructor(public dialogRef: MatDialogRef) {} + + fileCtrl = new FormControl(); + + async save(): Promise { + if (!this.fileCtrl.value) { + return; + } + + const file = this.fileCtrl.value as File; + + // We're reading the file as base64 data + const reader = new FileReader(); + const base64 = await this.readFileAsBase64(file); + + const viewpoint: BcfViewpoint = { + id: getNewRandomGuid(), + clippingPlanes: [], + lines: [], + viewpointComponents: { + coloring: [], + selectedComponents: [], + visibility: { + defaultVisibility: true, + exceptions: [], + }, + }, + snapshotBase64: base64, + }; + + this.dialogRef.close(viewpoint); + } + + close(): void { + this.dialogRef.close(); + } + + clear(): void { + this.fileCtrl.setValue(null); + } + + private readFileAsBase64(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => { + const dataUrl = reader.result as string; + // We want everything after the comma + const base64 = dataUrl.split(',')[1]; + resolve(base64); + }; + reader.onerror = reject; + reader.readAsDataURL(file); + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.html b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.html new file mode 100644 index 00000000..41422688 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.html @@ -0,0 +1,13 @@ +

Add {{ data.header }}

+ + + + {{ data.header }} + + + + + + + + diff --git a/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.scss b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.spec.ts new file mode 100644 index 00000000..77885b5b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddStringValueComponent } from './add-string-value.component'; + +describe('AddStringValueComponent', () => { + let component: AddStringValueComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddStringValueComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddStringValueComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.ts b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.ts new file mode 100644 index 00000000..b81a443e --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-string-value/add-string-value.component.ts @@ -0,0 +1,33 @@ +import { Component, Inject } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; +import { MatInputModule } from '@angular/material/input'; + +@Component({ + selector: 'bcfier-add-string-value', + standalone: true, + imports: [MatInputModule, FormsModule, MatDialogModule, MatButtonModule], + templateUrl: './add-string-value.component.html', + styleUrl: './add-string-value.component.scss', +}) +export class AddStringValueComponent { + value = ''; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { header: string } + ) {} + + close(shouldSave: boolean): void { + if (shouldSave) { + this.dialogRef.close(this.value); + } else { + this.dialogRef.close(); + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.html b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.html new file mode 100644 index 00000000..bdd322c2 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.html @@ -0,0 +1,24 @@ +

Add User

+ + +
+ + Username + + +
+
+
+ + + + diff --git a/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.scss b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.scss new file mode 100644 index 00000000..205cf7a0 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.scss @@ -0,0 +1,5 @@ +.field-container { + padding: 10px; + display: flex; + flex-direction: column; +} diff --git a/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.spec.ts new file mode 100644 index 00000000..321b846d --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddUserComponent } from './add-user.component'; + +describe('AddUserComponent', () => { + let component: AddUserComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddUserComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddUserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.ts b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.ts new file mode 100644 index 00000000..0409e1e3 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/add-user/add-user.component.ts @@ -0,0 +1,46 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { + FormBuilder, + FormsModule, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; + +@Component({ + selector: 'bcfier-add-user', + standalone: true, + imports: [ + MatDialogModule, + MatInputModule, + MatButtonModule, + MatFormFieldModule, + ReactiveFormsModule, + FormsModule, + ], + templateUrl: './add-user.component.html', + styleUrl: './add-user.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AddUserComponent { + newUserForm = this.fb.group({ + name: ['', Validators.required], + }); + constructor( + public dialogRef: MatDialogRef, + private fb: FormBuilder + ) {} + + closeDialog(shouldSave: boolean): void { + if (!shouldSave) { + this.dialogRef.close(); + return; + } + + this.dialogRef.close(this.newUserForm.value.name); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.html b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.html new file mode 100644 index 00000000..1caa2eb7 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.html @@ -0,0 +1,117 @@ +
+
+ + +
+ +
+
+ +
+
+ + +
+ @if(isInNavisworks) { +
+ +
+ } @if(filteredTopics && filteredTopics.length > 1) { +
+ +
+ } + +
+ + Search + + @if (search) { + + } + + filter_list +
+
+ +
+ + + + + {{ topic.title }} + {{ + topic.creationDate | date : "dd.MM.yyyy" + }} + + + + + +
+ chat + {{ topic.comments.length }} +
+
+ visibility + {{ topic.viewpoints.length }} +
+
+
+
+
+
+
+
+ +
+
diff --git a/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.scss b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.scss new file mode 100644 index 00000000..fbab2882 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.scss @@ -0,0 +1,81 @@ +.wrapper { + display: flex; + flex-direction: row; + gap: 12px; + height: 100%; +} + +.issue-list { + margin-top: 4px; + margin-left: 4px; + display: flex; + width: 30%; + height: 100%; + overflow: auto; +} + +.issue-list-buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + margin-bottom: 4px; + gap: 8px; + + button { + flex: 1; + } +} + +.topic-list { + display: flex; + flex-direction: column; + gap: 12px; + overflow: auto; +} + +mat-form-field { + width: 100%; +} + +mat-card-content { + display: flex; + flex-direction: row; + gap: 12px; +} + +.topic-info { + display: flex; + flex-direction: row; + gap: 6px; +} + +.issue-details { + padding-left: 12px; + width: 70%; + overflow: auto; +} + +.filter-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; +} + +mat-drawer-container { + width: 100%; +} + +mat-drawer { + width: 90%; + padding: 5px; +} + +mat-drawer-content { + padding: 10px; + overflow: hidden; +} + +.filter-container { + height: inherit; +} diff --git a/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.spec.ts new file mode 100644 index 00000000..0d7c80bb --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BcfFileComponent } from './bcf-file.component'; + +describe('BcfFileComponent', () => { + let component: BcfFileComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BcfFileComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(BcfFileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.ts b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.ts new file mode 100644 index 00000000..9f22781a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bcf-file/bcf-file.component.ts @@ -0,0 +1,357 @@ +import { + BcfFile, + BcfTopic, + ViewpointsClient, +} from '../../generated-client/generated-client'; +import { ChangeDetectorRef, Component, Input, inject } from '@angular/core'; +import { FormGroup, FormsModule } from '@angular/forms'; +import { + IFilters, + IssueFiltersComponent, +} from '../issue-filters/issue-filters.component'; +import { + MessageType, + TeamsMessengerService, +} from '../../services/teams-messenger.service'; + +import { AppConfigService } from '../../services/AppConfigService'; +import { BcfFileAutomaticallySaveService } from '../../services/bcf-file-automaticaly-save.service'; +import { BulkTopicEditComponent } from '../bulk-edit-topic/bulk-edit-topic.component'; +import { CommonModule } from '@angular/common'; +import { IssueFilterService } from '../../services/issue-filter.service'; +import { IssueStatusesService } from '../../services/issue-statuses.service'; +import { IssueTypesService } from '../../services/issue-types.service'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDialog } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { NavisworksClashProgressMessengerService } from '../../services/messengers/navisworks-clash-progress-messenger.service'; +import { NavisworksClashSelectionComponent } from '../navisworks-clash-selection/navisworks-clash-selection.component'; +import { NavisworksClashesLoadingService } from '../../services/navisworks-clashes-loading.service'; +import { NotificationsService } from '../../services/notifications.service'; +import { ProjectUsersService } from '../../services/project-users.service'; +import { SafeUrlPipe } from '../../pipes/safe-url.pipe'; +import { SettingsMessengerService } from '../../services/settings-messenger.service'; +import { TopicDetailComponent } from '../topic-detail/topic-detail.component'; +import { TopicFilterPipe } from '../../pipes/topic-filter.pipe'; +import { TopicMessengerService } from '../../services/topic-messenger.service'; +import { TopicPreviewImageDirective } from '../../directives/topic-preview-image.directive'; +import { getNewRandomGuid } from '../../functions/uuid'; +import { take } from 'rxjs'; + +@Component({ + selector: 'bcfier-bcf-file', + standalone: true, + imports: [ + MatButtonModule, + MatInputModule, + CommonModule, + MatCardModule, + MatIconModule, + TopicPreviewImageDirective, + FormsModule, + TopicFilterPipe, + MatProgressBarModule, + TopicDetailComponent, + MatSidenavModule, + IssueFiltersComponent, + SafeUrlPipe, + ], + templateUrl: './bcf-file.component.html', + styleUrl: './bcf-file.component.scss', +}) +export class BcfFileComponent { + @Input() bcfFile!: BcfFile; + issueStatuses$ = inject(IssueStatusesService).issueStatuses; + issueTypes$ = inject(IssueTypesService).issueTypes; + users$ = inject(ProjectUsersService).users; + issueFilterService = inject(IssueFilterService); + bcfFileAutomaticallySaveService = inject(BcfFileAutomaticallySaveService); + teamsMessengerService = inject(TeamsMessengerService); + topicMessengerService = inject(TopicMessengerService); + settingsMessengerService = inject(SettingsMessengerService); + navisworksClashProgressMessengerService = inject( + NavisworksClashProgressMessengerService + ); + cdr = inject(ChangeDetectorRef); + selectedTopic: BcfTopic | null = null; + filteredTopics: BcfTopic[] = []; + isInNavisworks = + inject(AppConfigService).getFrontendConfig().isConnectedToNavisworks; + viewpointsClient = inject(ViewpointsClient); + navisworksClashesLoadingService = inject(NavisworksClashesLoadingService); + notificationsService = inject(NotificationsService); + private dialog = inject(MatDialog); + + ngOnInit() { + this.selectedTopic = this.bcfFile.topics[0] || null; + this.topicMessengerService.setSelectedTopic(this.selectedTopic); + this.cdr.detectChanges(); + this.filteredTopics = [...this.bcfFile.topics]; + } + + private _search = ''; + public set search(value: string) { + this._search = value; + } + public get search(): string { + return this._search; + } + + selectTopic(topic: BcfTopic) { + this.selectedTopic = topic; + this.topicMessengerService.setSelectedTopic(this.selectedTopic); + } + + addIssue(): void { + this.settingsMessengerService.settings.pipe(take(1)).subscribe((s) => { + const newIssue: BcfTopic = { + comments: [], + id: getNewRandomGuid(), + files: [], + labels: [], + referenceLinks: [], + documentReferences: [], + relatedTopicIds: [], + viewpoints: [], + assignedTo: '', + creationAuthor: s.username, + description: '', + priority: '', + title: 'New Issue', + topicStatus: '', + stage: '', + topicType: '', + serverAssignedId: '', + modifiedAuthor: '', + creationDate: new Date(), + }; + this.bcfFile.topics.push(newIssue); + this.selectedTopic = newIssue; + this.topicMessengerService.setSelectedTopic(this.selectedTopic); + this.filteredTopics = [...this.bcfFile.topics]; + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + }); + } + + removeIssue(): void { + if (!this.selectedTopic) { + return; + } + + this.bcfFile.topics = this.bcfFile.topics.filter( + (topic) => topic.id !== this.selectedTopic?.id + ); + + if (this.bcfFile.topics.length > 0) { + this.selectedTopic = this.bcfFile.topics[0]; + } else { + this.selectedTopic = null; + } + this.topicMessengerService.setSelectedTopic(this.selectedTopic); + this.filteredTopics = [...this.bcfFile.topics]; + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + } + + filterIssues(filters: FormGroup): void { + const { + withoutStatus, + status, + withoutType, + type, + withoutUser, + users, + issueRange, + } = filters.value; + if ( + withoutStatus === undefined || + (!withoutStatus && status === undefined) || + withoutType === undefined || + (!withoutType && type === undefined) || + withoutUser === undefined || + (!withoutUser && users === undefined) || + issueRange === undefined || + issueRange?.start === undefined || + issueRange?.end === undefined + ) { + return; + } + + const isValuePresentInFilters = + withoutStatus || + withoutType || + withoutUser || + !!status || + !!type || + !!users || + !!issueRange.start || + !!issueRange.end; + + this.filteredTopics = isValuePresentInFilters + ? [ + ...this.issueFilterService.filterIssue( + this.bcfFile.topics, + withoutStatus, + status || '', + withoutType, + type || '', + withoutUser, + users || [], + issueRange?.start, + issueRange?.end + ), + ] + : this.bcfFile.topics; + } + + addNavisworksClashIssues(): void { + this.dialog + .open(NavisworksClashSelectionComponent) + .afterClosed() + .subscribe( + (selection?: { + clashId: string; + onlyImportNew: boolean; + statusType: string | null; + }) => { + if (!selection) { + return; + } + this.notificationsService.info( + 'If there are many clashes, generation of the data could take a few minutes.' + ); + this.navisworksClashesLoadingService.showLoadingScreen(); + + const existingIds = selection.onlyImportNew + ? this.bcfFile.topics + .filter( + (topic) => + !!topic.serverAssignedId && + // We only want to take Guids, as other server assigned ids might not originate from Navisworks + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test( + topic.serverAssignedId + ) + ) + .map((topic) => topic.serverAssignedId!) + : []; + + const cancellationSubscription = + this.navisworksClashProgressMessengerService.cancelGeneration.subscribe( + () => { + this.viewpointsClient + .cancelNavisworksClashDetection(selection.clashId) + .subscribe(() => { + /* Not doing anything with the response, that's handled later */ + }); + } + ); + + this.viewpointsClient + .createNavisworksClashDetectionResultIssues({ + clashId: selection.clashId, + excludedClashIds: existingIds, + status: selection.statusType, + shouldMoveBoundingBoxToCenterOfClash: true, + }) + .subscribe({ + next: (createdTopics) => { + this.navisworksClashesLoadingService.hideLoadingScreen(); + cancellationSubscription.unsubscribe(); + this.settingsMessengerService.settings + .pipe(take(1)) + .subscribe((s) => { + createdTopics.forEach((topic) => { + topic.creationAuthor = s.username; + }); + + if (selection.onlyImportNew) { + // In that case, we're filtering out those topics that already exist in the + createdTopics = createdTopics.filter( + (topic) => + !this.bcfFile.topics.some( + (existingTopic) => + existingTopic.serverAssignedId === + topic.serverAssignedId + ) + ); + } + + // Now we're trying to change topics that we have already imported if their status + // has changed, so we don't import them again but just update their status + + const topicsToAdd: BcfTopic[] = []; + createdTopics.forEach((createdTopic) => { + // We'll check if it exists already, and if it does, we'll just update the status + var existingTopic = this.bcfFile.topics.find( + (existing) => + existing.serverAssignedId === + createdTopic.serverAssignedId + ); + if (existingTopic) { + existingTopic.topicStatus = createdTopic.topicStatus; + } else { + topicsToAdd.push(createdTopic); + } + }); + + this.bcfFile.topics.push(...topicsToAdd); + this.filteredTopics = [...this.bcfFile.topics]; + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + + this.teamsMessengerService.sendMessageToTeams( + MessageType.AddNavisworksClashes + ); + }); + }, + error: (error) => { + this.navisworksClashesLoadingService.hideLoadingScreen(); + cancellationSubscription.unsubscribe(); + console.error(error); + this.notificationsService.error( + 'Failed to generate the clash data from Navisworks, this is probably a timeout issue' + ); + }, + }); + } + ); + } + + setResponsibleForAll(): void { + this.dialog + .open(BulkTopicEditComponent) + .afterClosed() + .subscribe( + (bulkOptions?: { + responsibleUser?: string; + status?: string; + type?: string; + }) => { + if (!bulkOptions) { + return; + } + + this.filteredTopics.forEach((topic) => { + if (bulkOptions.status) { + topic.topicStatus = + bulkOptions.status === '' ? undefined : bulkOptions.status; + } + if (bulkOptions.type) { + topic.topicType = + bulkOptions.type === '' ? undefined : bulkOptions.type; + } + if (bulkOptions.responsibleUser) { + topic.assignedTo = + bulkOptions.responsibleUser === '' + ? undefined + : bulkOptions.responsibleUser; + } + }); + + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + } + ); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.html b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.html new file mode 100644 index 00000000..ee70ef9a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.html @@ -0,0 +1,39 @@ +

Bulk Set Topic Data

+
+

You can set data for all currently filtered topics.

+ +
+ + Responsible + + @for (user of (users$ | async)?.values(); track user.id) { + {{ + user.identifier || "No Responsible" + }} + } + + + + + Type + + @for (type of (issueTypes$ | async)?.values(); track type) { + {{ type || "No Type" }} + } + + + + + Status + + @for (status of (issueStatuses$ | async)?.values(); track status) { + {{ status || "No Status" }} + } + + +
+
+
+ + +
diff --git a/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.scss b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.scss new file mode 100644 index 00000000..10ca2c42 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.scss @@ -0,0 +1,5 @@ +.info-select { + display: flex; + flex-direction: row; + gap: 12px; +} diff --git a/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.spec.ts new file mode 100644 index 00000000..7184ddd1 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BulkTopicEditComponent } from './bulk-edit-topic.component'; + +describe('BulkTopicEditComponent', () => { + let component: BulkTopicEditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BulkTopicEditComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(BulkTopicEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.ts b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.ts new file mode 100644 index 00000000..de294df5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/bulk-edit-topic/bulk-edit-topic.component.ts @@ -0,0 +1,56 @@ +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { MatSelectChange, MatSelectModule } from '@angular/material/select'; +import { ProjectUsersService } from '../../services/project-users.service'; +import { AsyncPipe } from '@angular/common'; +import { ProjectUserGet } from '../../generated-client/generated-client'; +import { IssueStatusesService } from '../../services/issue-statuses.service'; +import { IssueTypesService } from '../../services/issue-types.service'; +import { map } from 'rxjs'; + +@Component({ + selector: 'bcfier-bulk-edit-topic', + standalone: true, + imports: [MatButtonModule, MatDialogModule, MatSelectModule, AsyncPipe], + templateUrl: './bulk-edit-topic.component.html', + styleUrl: './bulk-edit-topic.component.scss', +}) +export class BulkTopicEditComponent { + private dialogRef = inject(MatDialogRef); + users$ = inject(ProjectUsersService).users.pipe( + map((users) => [{ id: '', identifier: '' }, ...users]) + ); + issueStatusesService = inject(IssueStatusesService); + issueTypesService = inject(IssueTypesService); + projectUsersService = inject(ProjectUsersService); + + issueStatuses$ = this.issueStatusesService.issueStatuses.pipe( + map((stati) => new Set(['', ...stati])) + ); + issueTypes$ = this.issueTypesService.issueTypes.pipe( + map((types) => new Set(['', ...types])) + ); + + selectedUser: ProjectUserGet | null = null; + selectedType: string | null = null; + selectedStatus: string | null = null; + + refreshUsers(): void { + this.projectUsersService.refreshUsers(); + } + + save(): void { + if (this.selectedUser || this.selectedType || this.selectedStatus) { + this.dialogRef.close({ + responsibleUser: this.selectedUser?.identifier, + type: this.selectedType, + status: this.selectedStatus, + }); + } + } + + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.html b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.html new file mode 100644 index 00000000..ff584feb --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.html @@ -0,0 +1,7 @@ +

CAD Plugin Error

+ +
{{ errorMessage }}
+
+ + + diff --git a/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.scss b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.spec.ts new file mode 100644 index 00000000..46ecc16d --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CadErrorDialogComponent } from './cad-error-dialog.component'; + +describe('CadErrorDialogComponent', () => { + let component: CadErrorDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CadErrorDialogComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CadErrorDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.ts b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.ts new file mode 100644 index 00000000..b51c6e18 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/cad-error-dialog/cad-error-dialog.component.ts @@ -0,0 +1,26 @@ +import { Component, Inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; + +@Component({ + selector: 'bcfier-cad-error-dialog', + standalone: true, + imports: [MatButtonModule, MatDialogModule], + templateUrl: './cad-error-dialog.component.html', + styleUrl: './cad-error-dialog.component.scss', +}) +export class CadErrorDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) + public errorMessage: string + ) {} + + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.html b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.html new file mode 100644 index 00000000..3a2e6528 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.html @@ -0,0 +1,44 @@ + + + +
+ + +
+
+ +
+ + {{ comment.author }} + {{ comment.creationDate | date : "dd.MM.yyyy HH:mm" }} + + + +

{{ comment.text }}

+
+
+ + + Add comment + + + + +
diff --git a/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.scss b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.scss new file mode 100644 index 00000000..bd112b04 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.scss @@ -0,0 +1,32 @@ +.comment-field { + width: 100%; +} + +.image-title { + display: flex; + justify-content: center; +} + +.viewpoint-image { + max-width: 100%; + max-height: 300px; + cursor: pointer; +} + +.comment-author { + margin-right: 8px; +} + +mat-card-content { + padding-top: 12px; +} + +.image-buttons { + position: absolute; + right: 0px; +} + +mat-card { + margin-bottom: 10px; + padding: 10px; +} diff --git a/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.spec.ts new file mode 100644 index 00000000..544dc17b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CommentsDetailComponent } from './comments-detail.component'; + +describe('CommentsDetailComponent', () => { + let component: CommentsDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CommentsDetailComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(CommentsDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.ts b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.ts new file mode 100644 index 00000000..46641ea9 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/comments-detail/comments-detail.component.ts @@ -0,0 +1,125 @@ +import { + BcfComment, + BcfTopic, + BcfViewpoint, +} from '../../generated-client/generated-client'; +import { Component, Input, OnInit } from '@angular/core'; +import { + MessageType, + TeamsMessengerService, +} from '../../services/teams-messenger.service'; + +import { BackendService } from '../../services/BackendService'; +import { BcfFileAutomaticallySaveService } from '../../services/bcf-file-automaticaly-save.service'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { ImagePreviewComponent } from '../image-preview/image-preview.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDialog } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { NotificationsService } from '../../services/notifications.service'; +import { SettingsMessengerService } from '../../services/settings-messenger.service'; +import { ViewpointImageDirective } from '../../directives/viewpoint-image.directive'; +import { getNewRandomGuid } from '../../functions/uuid'; +import { take } from 'rxjs'; + +@Component({ + selector: 'bcfier-comments-detail', + standalone: true, + imports: [ + CommonModule, + FormsModule, + MatCardModule, + MatButtonModule, + MatIconModule, + MatInputModule, + ViewpointImageDirective, + ], + templateUrl: './comments-detail.component.html', + styleUrl: './comments-detail.component.scss', +}) +export class CommentsDetailComponent implements OnInit { + @Input() comments!: BcfComment[]; + @Input() viewpoint: BcfViewpoint | null = null; + @Input() topic!: BcfTopic; + + newComment = ''; + + constructor( + private settingsMessengerService: SettingsMessengerService, + private notificationsService: NotificationsService, + private matDialog: MatDialog, + private backendService: BackendService, + private bcfFileAutomaticallySaveService: BcfFileAutomaticallySaveService, + private teamsMessengerService: TeamsMessengerService + ) {} + + ngOnInit(): void {} + + addComment(): void { + if (!this.newComment) { + return; + } + + this.settingsMessengerService.settings + .pipe(take(1)) + .subscribe((settings) => { + const newComment = { + id: getNewRandomGuid(), + author: settings.username, + creationDate: new Date(), + viewpointId: this.viewpoint?.id, + text: this.newComment, + }; + + this.topic.comments.push(newComment); + this.newComment = ''; + + this.notificationsService.success('Comment added'); + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + this.teamsMessengerService.sendMessageToTeams(MessageType.AddComment); + }); + } + + removeComment(comment: BcfComment): void { + this.topic.comments = this.topic.comments.filter( + (c) => c.id !== comment.id + ); + + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + this.notificationsService.success('Comment removed'); + } + + deleteViewpoint(viewpoint: BcfViewpoint): void { + this.topic.viewpoints = this.topic.viewpoints.filter( + (v) => v.id !== viewpoint.id + ); + + this.topic.comments.forEach((c) => { + if (c.viewpointId === viewpoint.id) { + c.viewpointId = undefined; + } + }); + + // When we're deleting a viewpoint, we also want to ensure that + // all other places where the comments are used are reevaluated, + // since comments that originally belonged to the viewpoint + // are moved to general comments now + this.topic.comments = [...this.topic.comments]; + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + } + + showImageFullScreen(viewpoint: BcfViewpoint): void { + this.matDialog.open(ImagePreviewComponent, { + data: viewpoint, + }); + } + + selectViewpoint(): void { + if (this.viewpoint) { + this.backendService.selectViewpoint(this.viewpoint); + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.html b/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.html new file mode 100644 index 00000000..3efd6a72 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.html @@ -0,0 +1,6 @@ +

Confirmation

+
Are you sure you want to perform {{ action }}?
+
+ + +
diff --git a/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.scss b/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.ts b/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.ts new file mode 100644 index 00000000..a771d242 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/confirm-dialog/confirm-dialog.component.ts @@ -0,0 +1,36 @@ +import { CommonModule } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + Inject, + inject, +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; +export type IConfirmdialogAction = 'delete'; +@Component({ + selector: 'bcfier-confirm-dialog', + standalone: true, + imports: [MatButtonModule, MatDialogModule], + templateUrl: './confirm-dialog.component.html', + styleUrl: './confirm-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ConfirmDialogComponent { + action: string; + private dialogRef = inject(MatDialogRef); + constructor( + @Inject(MAT_DIALOG_DATA) + public data: IConfirmdialogAction + ) { + this.action = data; + } + + close(confirm: boolean): void { + this.dialogRef.close(confirm); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.html b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.html new file mode 100644 index 00000000..7abfeb27 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.html @@ -0,0 +1,3 @@ + + + diff --git a/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.scss b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.scss new file mode 100644 index 00000000..f19063ed --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.scss @@ -0,0 +1,4 @@ +img { + max-width: 100%; + max-height: 100%; +} diff --git a/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.spec.ts new file mode 100644 index 00000000..b4e2a5f5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImagePreviewComponent } from './image-preview.component'; + +describe('ImagePreviewComponent', () => { + let component: ImagePreviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ImagePreviewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ImagePreviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.ts b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.ts new file mode 100644 index 00000000..0f83ebf5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/image-preview/image-preview.component.ts @@ -0,0 +1,22 @@ +import { Component, Inject } from '@angular/core'; +import { + MAT_DIALOG_DATA, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; +import { ViewpointImageDirective } from '../../directives/viewpoint-image.directive'; +import { BcfViewpoint } from '../../generated-client/generated-client'; + +@Component({ + selector: 'bcfier-image-preview', + standalone: true, + imports: [MatDialogModule, ViewpointImageDirective], + templateUrl: './image-preview.component.html', + styleUrl: './image-preview.component.scss', +}) +export class ImagePreviewComponent { + constructor( + matDialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public viewpoint: BcfViewpoint + ) {} +} diff --git a/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.html b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.html new file mode 100644 index 00000000..690559b3 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.html @@ -0,0 +1,67 @@ +
+
+ Without Status + + Status + + @for (status of (issueStatuses$ | async)?.values(); track status) { + {{ status }} + } + + + Without Type + + Type + + @for (type of (issueTypes$ | async)?.values(); track type) { + {{ type }} + } + + + Without Responsible + + Responsible + + @for (user of (users$ | async); track user.id) { + {{ user.identifier }} + } + + + + Due Date + + + + + DD/MM/YYYY – DD/MM/YYYY + + + + @if (filtersForm.get('issueRange.start')?.hasError('matStartDateInvalid')) + { + Invalid start date + } @if (filtersForm.get('issueRange.end')?.hasError('matEndDateInvalid')) { + Invalid end date + } + +
+ + +
diff --git a/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.scss b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.scss new file mode 100644 index 00000000..e7a97335 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.scss @@ -0,0 +1,30 @@ +.container { + display: flex; + justify-content: space-between; + flex-direction: column; + height: 99%; + &_filters { + flex: 1; + } +} + +mat-form-field { + width: 100%; +} + +button { + margin: 5px; +} + +::ng-deep .panel-bg.mat-mdc-select-panel { + background: black; + opacity: 0.85; +} + +::ng-deep .mat-pseudo-checkbox-full { + border-color: var(--primary-color) !important; +} + +mat-option { + color: var(--primary-color); +} diff --git a/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.ts b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.ts new file mode 100644 index 00000000..e89dbc47 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/issue-filters/issue-filters.component.ts @@ -0,0 +1,134 @@ +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + Output, + inject, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + ReactiveFormsModule, +} from '@angular/forms'; + +import { AsyncPipe } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; +import { Observable } from 'rxjs'; +import { ProjectUserGet } from '../../generated-client/generated-client'; +import { ProjectUsersService } from '../../services/project-users.service'; + +export interface IFilters { + withoutStatus: FormControl; + status: FormControl; + withoutType: FormControl; + type: FormControl; + withoutUser: FormControl; + users: FormControl; + issueRange: FormGroup<{ + start: FormControl; + end: FormControl; + }>; +} + +@Component({ + selector: 'bcfier-issue-filters', + standalone: true, + imports: [ + MatFormFieldModule, + MatSelectModule, + MatButtonModule, + AsyncPipe, + ReactiveFormsModule, + MatDatepickerModule, + MatCheckboxModule, + ], + styleUrl: './issue-filters.component.scss', + templateUrl: './issue-filters.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class IssueFiltersComponent { + @Input({ + required: true, + }) + issueStatuses$!: Observable>; + + @Input({ + required: true, + }) + issueTypes$!: Observable>; + + @Input({ + required: true, + }) + users$!: Observable; + projectUsersService = inject(ProjectUsersService); + + @Output() + acceptedFilters = new EventEmitter>(); + + fb = inject(FormBuilder); + + filtersForm: FormGroup; + constructor() { + this.filtersForm = this.fb.group({ + withoutStatus: new FormControl(false, { nonNullable: true }), + status: new FormControl('', { nonNullable: true }), + withoutType: new FormControl(false, { nonNullable: true }), + type: new FormControl('', { nonNullable: true }), + withoutUser: new FormControl(false, { nonNullable: true }), + users: new FormControl([], { nonNullable: true }), + issueRange: new FormGroup({ + start: new FormControl(null), + end: new FormControl(null), + }), + }); + + this.filtersForm.valueChanges.subscribe((value) => { + if (value.withoutStatus && this.filtersForm.controls.status.enabled) { + this.filtersForm.controls.status.disable(); + } else if ( + !value.withoutStatus && + this.filtersForm.controls.status.disabled + ) { + this.filtersForm.controls.status.enable(); + } + + if (value.withoutType && this.filtersForm.controls.type.enabled) { + this.filtersForm.controls.type.disable(); + } else if ( + !value.withoutType && + this.filtersForm.controls.type.disabled + ) { + this.filtersForm.controls.type.enable(); + } + + if (value.withoutUser && this.filtersForm.controls.users.enabled) { + this.filtersForm.controls.users.disable(); + } else if ( + !value.withoutUser && + this.filtersForm.controls.users.disabled + ) { + this.filtersForm.controls.users.enable(); + } + }); + } + + acceptFilters(): void { + this.acceptedFilters.emit(this.filtersForm); + } + + clearFilters(): void { + this.filtersForm.reset(); + this.acceptedFilters.emit(this.filtersForm); + } + + refreshUsers(): void { + this.projectUsersService.refreshUsers(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.html b/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.html new file mode 100644 index 00000000..732e8346 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.html @@ -0,0 +1,5 @@ +@for(file of lastOpenedFiles() ;track file.fileName) { + +} diff --git a/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.scss b/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.ts b/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.ts new file mode 100644 index 00000000..37f87b7a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/last-opened-files/last-opened-files.component.ts @@ -0,0 +1,74 @@ +import { + ChangeDetectionStrategy, + Component, + effect, + inject, + input, +} from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { LastOpenedFileGet } from '../../generated-client/generated-client'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { FileNamePipe } from '../../pipes/file-name.pipe'; +import { BcfFilesMessengerService } from '../../services/bcf-files-messenger.service'; +import { take } from 'rxjs'; +import { mapToCanActivate } from '@angular/router'; +import { BackendService } from '../../services/BackendService'; +import { NotificationsService } from '../../services/notifications.service'; + +@Component({ + selector: 'bcfier-last-opened-files', + standalone: true, + imports: [MatMenuModule, MatButtonModule, MatTooltipModule, FileNamePipe], + templateUrl: './last-opened-files.component.html', + styleUrl: './last-opened-files.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class LastOpenedFilesComponent { + isOpen = input(false); + btnWidth = input(0); + lastOpenedFiles = input([]); + private bcfFilesMessengerService = inject(BcfFilesMessengerService); + private backendService = inject(BackendService); + private notificationsService = inject(NotificationsService); + + constructor() { + effect(() => { + this.setButtonWidth(); + }); + } + + setButtonWidth(): void { + if (this.isOpen()) { + const panel = ( + document.getElementsByClassName('mat-mdc-menu-panel')[0] + ); + if (panel) { + panel.style.width = this.btnWidth() + 'px'; + } + } + } + + openFile(file: LastOpenedFileGet): void { + this.bcfFilesMessengerService.bcfFiles + .pipe(take(1)) + .subscribe((bcfFiles) => { + const matchingFile = bcfFiles.find((f) => f.fileName === file.fileName); + if (matchingFile) { + this.bcfFilesMessengerService.setBcfFileSelected(matchingFile); + } else { + this.backendService.importBcfFile(file.fileName).subscribe({ + next: (bcfFileWrapper) => { + this.bcfFilesMessengerService.openBcfFile(bcfFileWrapper); + }, + error: () => { + this.notificationsService.error( + file.fileName, + 'Could not open file' + ); + }, + }); + } + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.html b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.html new file mode 100644 index 00000000..6f89c3c0 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.html @@ -0,0 +1,8 @@ +

Loading...

+ + + diff --git a/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.scss b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.scss new file mode 100644 index 00000000..f8a73298 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.scss @@ -0,0 +1,10 @@ +mat-dialog-content { + width: 50vw; + height: 50vh; +} + +.loading-screen { + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.spec.ts new file mode 100644 index 00000000..2bdcd9e9 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoadingScreenComponent } from './loading-screen.component'; + +describe('LoadingScreenComponent', () => { + let component: LoadingScreenComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [LoadingScreenComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LoadingScreenComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.ts b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.ts new file mode 100644 index 00000000..691ae58a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/loading-screen/loading-screen.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; + +@Component({ + selector: 'bcfier-loading-screen', + standalone: true, + imports: [MatProgressSpinnerModule, MatDialogModule], + templateUrl: './loading-screen.component.html', + styleUrl: './loading-screen.component.scss', +}) +export class LoadingScreenComponent {} diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.html b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.html new file mode 100644 index 00000000..0fa5f890 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.html @@ -0,0 +1,38 @@ +

Select Clash Test

+ +

+ You can select which clash to export. Large tests may take some time to + generate. +

+ + + Clash Check + + @for (clash of clashes; track clash) { + {{ clash.displayName }} + } + + + + Status + + All / No Filter + New + Active + Reviewed + Approved + Resolved + + + Only Import New Clashes +
+ + + + diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.scss b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.scss new file mode 100644 index 00000000..b258ed2b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.scss @@ -0,0 +1,4 @@ +mat-dialog-content { + display: flex; + flex-direction: column; +} diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.spec.ts new file mode 100644 index 00000000..010c5ff4 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NavisworksClashSelectionComponent } from './navisworks-clash-selection.component'; + +describe('NavisworksClashSelectionComponent', () => { + let component: NavisworksClashSelectionComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NavisworksClashSelectionComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(NavisworksClashSelectionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.ts b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.ts new file mode 100644 index 00000000..26d98b6a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clash-selection/navisworks-clash-selection.component.ts @@ -0,0 +1,65 @@ +import { Component, inject } from '@angular/core'; +import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { + NavisworksClashSelection, + ViewpointsClient, +} from '../../generated-client/generated-client'; + +import { FormsModule } from '@angular/forms'; +import { LoadingService } from '../../services/loading.service'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; + +@Component({ + selector: 'bcfier-navisworks-clash-selection', + standalone: true, + imports: [ + MatInputModule, + MatDialogModule, + MatButtonModule, + MatSelectModule, + MatCheckboxModule, + FormsModule, + MatTooltipModule, + ], + templateUrl: './navisworks-clash-selection.component.html', + styleUrl: './navisworks-clash-selection.component.scss', +}) +export class NavisworksClashSelectionComponent { + viewpointsClient = inject(ViewpointsClient); + loadingService = inject(LoadingService); + onlyImportNew = false; + constructor( + public dialogRef: MatDialogRef + ) { + this.loadingService.showLoadingScreen(); + this.viewpointsClient.getAvailableNavisworksClashes().subscribe({ + next: (clashes) => { + this.loadingService.hideLoadingScreen(); + this.clashes = clashes; + }, + error: () => { + this.loadingService.hideLoadingScreen(); + }, + }); + } + + clashes: NavisworksClashSelection[] = []; + selectedClashId: string | null = null; + selectedStatusType: string | null = null; + + save(): void { + this.dialogRef.close({ + clashId: this.selectedClashId, + onlyImportNew: this.onlyImportNew, + statusType: this.selectedStatusType, + }); + } + + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.html b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.html new file mode 100644 index 00000000..924cc092 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.html @@ -0,0 +1,27 @@ +

Generating clashes...

+@if(currentCount > 0 && totalCount > 0) { +

{{ currentCount }} of {{ totalCount }}

+} + + @if(currentCount > 0 && totalCount > 0) { + + } @else { + + } + + +

+ Cancelling still saves the generated clashes so far, but does stop generating + more issues. +

diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.scss b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.scss new file mode 100644 index 00000000..f8a73298 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.scss @@ -0,0 +1,10 @@ +mat-dialog-content { + width: 50vw; + height: 50vh; +} + +.loading-screen { + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.spec.ts new file mode 100644 index 00000000..ee9a6197 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NavisworksClashesLoadingScreenComponent } from './navisworks-clashes-loading-screen.component'; + +describe('NavisworksClashesLoadingScreenComponent', () => { + let component: NavisworksClashesLoadingScreenComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NavisworksClashesLoadingScreenComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(NavisworksClashesLoadingScreenComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.ts b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.ts new file mode 100644 index 00000000..77128194 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component.ts @@ -0,0 +1,69 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Subject, takeUntil } from 'rxjs'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { NavisworksClashProgressMessengerService } from '../../services/messengers/navisworks-clash-progress-messenger.service'; + +@Component({ + selector: 'bcfier-navisworks-clashes-loading-screen', + standalone: true, + imports: [MatProgressSpinnerModule, MatDialogModule, MatButtonModule], + templateUrl: './navisworks-clashes-loading-screen.component.html', + styleUrl: './navisworks-clashes-loading-screen.component.scss', +}) +export class NavisworksClashesLoadingScreenComponent + implements OnDestroy, OnInit +{ + constructor( + private navisworksClashProgressMessengerService: NavisworksClashProgressMessengerService + ) {} + + private $destroy = new Subject(); + + totalCount = 0; + currentCount = 0; + currentProgress = 0; + + ngOnInit(): void { + this.navisworksClashProgressMessengerService.navisworksClashesTotalCount + .pipe(takeUntil(this.$destroy)) + .subscribe((totalCount) => { + this.totalCount = totalCount; + this.calculateProgress(); + }); + + this.navisworksClashProgressMessengerService.navisworksClashesCurrentCount + .pipe(takeUntil(this.$destroy)) + .subscribe((currentCount) => { + if (currentCount > this.currentCount) { + this.currentCount = currentCount; + this.calculateProgress(); + } + }); + } + + private calculateProgress(): void { + if (this.totalCount === 0) { + this.currentProgress = 0; + return; + } + + const currentProgress = (100 * this.currentCount) / this.totalCount; + if (currentProgress > this.currentProgress) { + // We don't want to go backwards for the progress bar if we + // receive earlier messages later + this.currentProgress = currentProgress; + } + } + + ngOnDestroy(): void { + this.$destroy.next(); + this.$destroy.complete(); + } + + cancelGeneration(): void { + this.navisworksClashProgressMessengerService.cancelGeneration.next(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.html b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.html new file mode 100644 index 00000000..04e2bb32 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.html @@ -0,0 +1,92 @@ +

{{ data ? "Edit" : "Create" }} Project

+ + +
+ + Project name + + + + Teams webhook + + +
+
+ + @if(data) { + + + + + Add user + + @if(panelOpenState) { + remove + } @else { + add + } + + + User identifier + + + @for (user of filteredUsers$ | async; track user) { + {{ user.identifier }} + } + + + + + + + @for(user of (users$ | async); track user.id; let count = $count) { + + + User identifier + + + delete + + } + + } +
+ + + + diff --git a/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.scss b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.scss new file mode 100644 index 00000000..ce89acfc --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.scss @@ -0,0 +1,56 @@ +.field-container { + padding: 10px; + display: flex; + flex-direction: column; +} + +mat-list-item { + height: 100% !important; +} + +.mat-expansion-panel .mat-expansion-panel-header-title { + color: black; + align-items: center; +} + +.mat-expansion-panel .mat-expansion-panel-header-description { + font-weight: lighter; + color: black; +} + +.mat-expansion-panel-header { + color: black; + background-color: var(--primary-color); +} + +mat-expansion-panel-header.mat-expanded, +mat-expansion-panel-header.mat-expanded:focus { + background-color: var(--primary-color); +} + +.mat-expansion-panel:not(.mat-expanded) + .mat-expansion-panel-header:hover:not([aria-disabled="true"]) { + background-color: var(--primary-color); +} + +.mat-expansion-panel.mat-expanded + .mat-expansion-panel-header:hover:not([aria-disabled="true"]) { + background-color: var(--primary-color); +} + +.mat-expansion-panel:not(.mat-expanded) { + border-radius: 8px !important; + margin: 16px 0; +} + +.mat-expansion-panel.mat-expanded .mat-expansion-panel-header { + border-radius: 8px 8px 0 0 !important; +} + +.add-user-btn { + margin-left:10px; +} + +mat-icon { + cursor: pointer; +} diff --git a/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.ts b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.ts new file mode 100644 index 00000000..71350212 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/project-details/project-details.component.ts @@ -0,0 +1,175 @@ +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + Inject, + OnDestroy, + inject, +} from '@angular/core'; +import { + FormBuilder, + FormsModule, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { + MAT_DIALOG_DATA, + MatDialog, + MatDialogModule, + MatDialogRef, +} from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { + EMPTY, + Observable, + Subject, + catchError, + filter, + map, + of, + switchMap, + tap, +} from 'rxjs'; +import { MatListModule } from '@angular/material/list'; +import { AsyncPipe } from '@angular/common'; +import { + ProjectGet, + ProjectUserGet, + ProjectUsersClient, + UserGet, + UsersClient, +} from '../../generated-client/generated-client'; +import { MatButtonModule } from '@angular/material/button'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatIconModule } from '@angular/material/icon'; +import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'; +import { ProjectUsersService } from '../../services/project-users.service'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { NotificationsService } from '../../services/notifications.service'; +@Component({ + selector: 'bcfier-project-details', + standalone: true, + imports: [ + MatFormFieldModule, + MatInputModule, + FormsModule, + MatListModule, + AsyncPipe, + ReactiveFormsModule, + MatDialogModule, + MatButtonModule, + MatExpansionModule, + MatIconModule, + MatAutocompleteModule, + ], + templateUrl: './project-details.component.html', + styleUrl: './project-details.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ProjectDetailsComponent implements OnDestroy { + users$: Observable | null = null; + projectDetailsForm = this.fb.group({ + name: ['', Validators.required], + teamsWebhook: [''], + }); + panelOpenState = false; + identifier = ''; + private allUsers$ = inject(UsersClient).getAllUsers(); + filteredUsers$ = new Subject(); + private notificationsService = inject(NotificationsService); + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) + public data: ProjectGet, + private projectUsersClient: ProjectUsersClient, + private fb: FormBuilder, + private cdr: ChangeDetectorRef, + private matDialog: MatDialog, + private projectUsersService: ProjectUsersService + ) { + if (data) { + this.projectDetailsForm.patchValue({ + name: data.name, + teamsWebhook: data?.teamsWebhook, + }); + this.users$ = this.getProjectUsers(data.id); + } + this.filterUsers(); + } + + filterUsers(): void { + this.allUsers$.subscribe((users) => { + if (this.identifier) { + this.filteredUsers$.next( + users.filter( + (u) => + u.identifier + .toLowerCase() + .indexOf(this.identifier.toLowerCase()) !== -1 + ) + ); + } else { + this.filteredUsers$.next(users); + } + }); + } + + ngOnDestroy(): void { + this.filteredUsers$.complete(); + } + + getProjectUsers(projectId: string): Observable { + return this.projectUsersClient.getProjectUsersForProject(projectId); + } + + updateProjectDetails(isUpdate: boolean): void { + if (!isUpdate) { + this.dialogRef.close(); + return; + } + this.dialogRef.close(this.projectDetailsForm.value); + } + + addUserToProject(): void { + this.users$ = this.projectUsersClient + .addUserToProject(this.data.id, { + identifier: this.identifier, + }) + .pipe( + tap({ + next: (u) => { + this.notificationsService.success('User added'); + this.projectUsersService.setUsers(u); + this.identifier = ''; + this.filterUsers(); + this.cdr.detectChanges(); + }, + error: () => { + this.notificationsService.error('Failed to add the user'); + this.users$ = this.getProjectUsers(this.data.id); + this.filterUsers(); + this.cdr.detectChanges(); + }, + }) + ); + } + + deleteProjectUser(userId: string): void { + this.matDialog + .open(ConfirmDialogComponent, { + autoFocus: false, + restoreFocus: false, + data: 'delete', + }) + .afterClosed() + .subscribe((confirm) => { + if (confirm) { + this.users$ = this.projectUsersClient + .deleteProjectUser(this.data.id, userId) + .pipe(tap((u) => this.projectUsersService.setUsers(u))); + this.cdr.detectChanges(); + } + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.html b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.html new file mode 100644 index 00000000..f02d75df --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.html @@ -0,0 +1,84 @@ +
+ + Filter + + + @if(shouldEnableProjectManagement) { + + } + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
Name{{ row.name }}Created + {{ row.createdAtUtc | date : "dd.MM.yyyy HH:mm" }} + +
+ + @if(row.id === selectedProject?.id) { bookmark } @else { + bookmark_border } + + @if(shouldEnableProjectManagement) { + + delete + + } +
+
+ @if(filter) { + + No data matching the filter "{{ filter }}" + + } +
+ + +
diff --git a/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.scss b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.scss new file mode 100644 index 00000000..2be343da --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.scss @@ -0,0 +1,40 @@ +.top-part { + display:flex; + justify-content: space-between; + align-items: top; + gap:20px; + + button { + margin-top: 8px; + } + + padding-right: 8px; +} + +.table-wrap { + max-height: 50vh; + overflow-y: auto; +} + +mat-form-field { + width: 100%; +} + +.mat-column-actions { + width: 100px; + text-align: end; +} + +mat-icon { + cursor: pointer; +} + +tr.project-row:hover { + background: whitesmoke; +} + +.action-btn-container { + display: flex; + gap: 5px; + align-items: center; +} diff --git a/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.ts b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.ts new file mode 100644 index 00000000..e577da34 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/projects-table/projects-table.component.ts @@ -0,0 +1,266 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + inject, +} from '@angular/core'; +import { AsyncPipe, CommonModule, DatePipe } from '@angular/common'; +import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { + ProjectGet, + ProjectPost, + ProjectPut, + ProjectUsersClient, + ProjectsClient, +} from '../../generated-client/generated-client'; +import { + Subject, + catchError, + combineLatestWith, + filter, + of, + switchMap, + take, + takeUntil, + tap, +} from 'rxjs'; + +import { AppConfigService } from '../../services/AppConfigService'; +import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { NotificationsService } from '../../services/notifications.service'; +import { ProjectDetailsComponent } from '../project-details/project-details.component'; +import { ProjectsService } from '../../services/light-query/projects.service'; +import { SelectedProjectMessengerService } from '../../services/selected-project-messenger.service'; +import { SettingsMessengerService } from '../../services/settings-messenger.service'; + +@Component({ + selector: 'bcfier-projects-table', + standalone: true, + imports: [ + CommonModule, + MatFormFieldModule, + MatInputModule, + MatTableModule, + MatSortModule, + MatPaginatorModule, + DatePipe, + AsyncPipe, + MatIconModule, + MatButtonModule, + FormsModule, + ], + templateUrl: './projects-table.component.html', + styleUrl: './projects-table.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ProjectsTableComponent + implements AfterViewInit, OnDestroy, OnInit +{ + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort!: MatSort; + + projectsService = inject(ProjectsService); + settingsMessengerService = inject(SettingsMessengerService); + notificationsService = inject(NotificationsService); + selectedProjectMessengerService = inject(SelectedProjectMessengerService); + projectsClient = inject(ProjectsClient); + projectUsersClient = inject(ProjectUsersClient); + matDialog = inject(MatDialog); + cdr = inject(ChangeDetectorRef); + appConfigService = inject(AppConfigService); + + private destroyed$ = new Subject(); + dataSource!: MatTableDataSource; + displayedColumns = ['name', 'createdAtUtc', 'actions']; + filter = ''; + selectedProject: ProjectGet | null = null; + shouldEnableProjectManagement = + this.appConfigService.shouldEnableProjectManagementFeatures(); + + constructor() { + this.projectsService + .connect() + .pipe(takeUntil(this.destroyed$)) + .subscribe((projects) => { + this.dataSource = new MatTableDataSource(projects); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + }); + } + + ngOnInit(): void { + this.selectedProjectMessengerService.selectedProject + .pipe(takeUntil(this.destroyed$)) + .subscribe((p) => { + this.selectedProject = p; + }); + this.projectsService.onSort({ + active: 'createdAtUtc', + direction: 'desc', + }); + } + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + ngAfterViewInit() { + if (this.dataSource) { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + } + + applyFilter(filter: string) { + this.projectsService.setQueryParameter( + 'filter', + filter.trim().toLowerCase() + ); + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } + + projectClicked(project: ProjectGet): void { + if (this.shouldEnableProjectManagement) { + this.openProjectDetails(project); + } else { + this.setSelectedProject(project); + } + } + + private openProjectDetails(project: ProjectGet): void { + this.matDialog + .open(ProjectDetailsComponent, { + autoFocus: false, + width: '80%', + maxHeight: '70vh', + data: project, + }) + .afterClosed() + .pipe( + filter((newProject) => !!newProject), + switchMap((editedProject: ProjectPut) => { + return this.projectsClient.editProject(project.id, { + ...editedProject, + id: project.id, + }); + }) + ) + .subscribe({ + next: (p) => { + this.selectedProjectMessengerService.setSelectedProject(p); + this.projectsService.forceRefresh(); + if (this.filter) { + this.applyFilter(this.filter); + } + this.notificationsService.success('Project updated'); + }, + error: () => {}, + }); + } + + createProject(): void { + this.matDialog + .open(ProjectDetailsComponent, { + autoFocus: false, + restoreFocus: false, + width: '80%', + maxHeight: '70vh', + }) + .afterClosed() + .pipe( + filter((newProject) => !!newProject), + switchMap((newProject: ProjectPost) => { + return this.projectsClient + .createProject(newProject) + .pipe( + combineLatestWith(this.settingsMessengerService.settings), + take(1) + ); + }), + switchMap(([p, s]) => { + return this.projectUsersClient + .addUserToProject(p.id, { + identifier: s.username, + }) + .pipe( + catchError((err) => { + this.projectsService.forceRefresh(); + + if (this.filter) { + this.applyFilter(this.filter); + } + this.notificationsService.success('Project created'); + this.notificationsService.info( + 'Current user was not added, please add manually' + ); + return of([]); + }), + tap(() => { + this.selectedProjectMessengerService.setSelectedProject(p); + }) + ); + }) + ) + .subscribe({ + next: () => { + this.projectsService.forceRefresh(); + + if (this.filter) { + this.applyFilter(this.filter); + } + this.notificationsService.success('Project created'); + }, + error: () => {}, + }); + } + + deleteProject(projectId: string): void { + this.matDialog + .open(ConfirmDialogComponent, { + autoFocus: false, + restoreFocus: false, + data: 'delete this project', + }) + .afterClosed() + .pipe( + filter((confirm) => !!confirm), + switchMap(() => this.projectsClient.deleteProject(projectId)) + ) + .subscribe({ + next: () => { + this.projectsService.forceRefresh(); + if (this.filter) { + this.applyFilter(this.filter); + } + }, + error: () => {}, + }); + } + + setSelectedProject(p: ProjectGet): void { + if (p.id === this.selectedProject?.id) { + this.selectedProjectMessengerService.setSelectedProject(null); + return; + } + this.selectedProjectMessengerService.setSelectedProject(p); + } + + refresh(): void { + this.projectsService.forceRefresh(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/settings/settings.component.html b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.html new file mode 100644 index 00000000..0a9a313d --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.html @@ -0,0 +1,32 @@ + + + +

Settings

+ + + Username + + + + Database Location + + + + + + + + +
+ +
diff --git a/src/ipa-bcfier-ui/src/app/components/settings/settings.component.scss b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.scss new file mode 100644 index 00000000..9ee20adf --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.scss @@ -0,0 +1,3 @@ +mat-form-field { + display: block; +} diff --git a/src/ipa-bcfier-ui/src/app/components/settings/settings.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.spec.ts new file mode 100644 index 00000000..b0f7d8f4 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingsComponent } from './settings.component'; + +describe('SettingsComponent', () => { + let component: SettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SettingsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/settings/settings.component.ts b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.ts new file mode 100644 index 00000000..b53dae4b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/settings/settings.component.ts @@ -0,0 +1,74 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { Subject, takeUntil } from 'rxjs'; + +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatInputModule } from '@angular/material/input'; +import { MatTabsModule } from '@angular/material/tabs'; +import { ProjectsTableComponent } from '../projects-table/projects-table.component'; +import { SettingsClient } from '../../generated-client/generated-client'; +import { SettingsMessengerService } from '../../services/settings-messenger.service'; +import { UsersComponent } from '../users/users.component'; + +@Component({ + selector: 'bcfier-settings', + standalone: true, + imports: [ + CommonModule, + MatDialogModule, + FormsModule, + MatInputModule, + MatButtonModule, + MatTabsModule, + ProjectsTableComponent, + UsersComponent, + ], + templateUrl: './settings.component.html', + styleUrl: './settings.component.scss', +}) +export class SettingsComponent implements OnInit, OnDestroy { + constructor( + private dialogRef: MatDialogRef, + public settingsMessengerService: SettingsMessengerService, + private settingsClient: SettingsClient + ) {} + + username: string = ''; + mainDatabaseSaveLocation: string = ''; + + private destroyed$ = new Subject(); + + ngOnInit(): void { + this.settingsMessengerService.settings + .pipe(takeUntil(this.destroyed$)) + .subscribe((settings) => { + this.username = settings.username; + this.mainDatabaseSaveLocation = settings.mainDatabaseLocation || ''; + }); + } + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + save(): void { + this.settingsMessengerService.saveSettings({ + username: this.username, + mainDatabaseLocation: this.mainDatabaseSaveLocation, + }); + this.close(); + } + + close(): void { + this.dialogRef.close(); + } + + changeMainDatabaseSaveLocation(): void { + this.settingsClient.choseMainDatabaseLocation().subscribe(() => { + this.settingsMessengerService.refreshSettings(); + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.html b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.html new file mode 100644 index 00000000..f1bf3e0e --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.html @@ -0,0 +1,56 @@ + + + + diff --git a/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.scss b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.scss new file mode 100644 index 00000000..8410a9b7 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.scss @@ -0,0 +1,22 @@ +.menu-buttons { + display: flex; + gap: 12px; +} + +.menu-band { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} +.version-label { + font-size: small; +} + +.project-name { + font-size: 16px; +} + +::ng-deep .mat-mdc-menu-content { + padding: 0 !important; +} diff --git a/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.spec.ts new file mode 100644 index 00000000..d10414ce --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TopMenuComponent } from './top-menu.component'; + +describe('TopMenuComponent', () => { + let component: TopMenuComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TopMenuComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TopMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.ts b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.ts new file mode 100644 index 00000000..f39fb3cb --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/top-menu/top-menu.component.ts @@ -0,0 +1,185 @@ +import { AsyncPipe, UpperCasePipe } from '@angular/common'; +import { + BcfFileWrapper, + LastOpenedFileGet, + LastOpenedFilesClient, + SettingsClient, +} from '../../generated-client/generated-client'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { + Subject, + combineLatestWith, + delay, + distinctUntilChanged, + of, + switchMap, + take, + takeUntil, +} from 'rxjs'; + +import { BackendService } from '../../services/BackendService'; +import { BcfFilesMessengerService } from '../../services/bcf-files-messenger.service'; +import { FormsModule } from '@angular/forms'; +import { LastOpenedFilesComponent } from '../last-opened-files/last-opened-files.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { NotificationsService } from '../../services/notifications.service'; +import { SelectedProjectMessengerService } from '../../services/selected-project-messenger.service'; +import { SettingsComponent } from '../settings/settings.component'; +import { version } from '../../version'; + +@Component({ + selector: 'bcfier-top-menu', + standalone: true, + imports: [ + MatIconModule, + MatButtonModule, + MatDialogModule, + UpperCasePipe, + AsyncPipe, + MatMenuModule, + LastOpenedFilesComponent, + MatCheckboxModule, + FormsModule, + ], + templateUrl: './top-menu.component.html', + styleUrl: './top-menu.component.scss', +}) +export class TopMenuComponent implements OnDestroy, OnInit { + private destroyed$ = new Subject(); + version = version.version; + selectedProject$ = inject(SelectedProjectMessengerService).selectedProject; + lastFileMenuOpened = false; + lastOpenedFiles: LastOpenedFileGet[] = []; + alwaysOnTopRequestRunning = false; + private _alwaysOnTop = true; + set alwaysOnTop(value: boolean) { + this._alwaysOnTop = value; + this.changeAlwaysOnTopInBackend(); + } + get alwaysOnTop(): boolean { + return this._alwaysOnTop; + } + + constructor( + private backendService: BackendService, + private notificationsService: NotificationsService, + private bcfFilesMessengerService: BcfFilesMessengerService, + private matDialog: MatDialog, + private lastOpenedFilesClient: LastOpenedFilesClient, + private settingsClient: SettingsClient + ) { + this.checkOpenedFileAndSendInfo(); + } + + private changeAlwaysOnTopInBackend(): void { + const isAlwaysOnTop = this._alwaysOnTop; + this.alwaysOnTopRequestRunning = true; + + this.settingsClient.getIsAlwaysOnTop().subscribe({ + next: (serverIsAlwaysOnTop) => { + if (serverIsAlwaysOnTop === isAlwaysOnTop) { + this.alwaysOnTopRequestRunning = false; + return; + } + + this.settingsClient.setIsAlwaysOnTop(isAlwaysOnTop).subscribe({ + next: () => { + this.alwaysOnTopRequestRunning = false; + }, + error: () => { + this.notificationsService.error( + 'Could not change always on top setting.' + ); + this.alwaysOnTopRequestRunning = false; + }, + }); + }, + error: () => { + this.notificationsService.error( + 'Could not change always on top setting.' + ); + this.alwaysOnTopRequestRunning = false; + }, + }); + } + + ngOnInit(): void { + this.settingsClient.getIsAlwaysOnTop().subscribe((isAlwaysOnTop) => { + this._alwaysOnTop = isAlwaysOnTop; + }); + } + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + openBcf(): void { + this.backendService.importBcfFile().subscribe({ + next: (bcfFileWrapper: BcfFileWrapper) => { + this.bcfFilesMessengerService.openBcfFile(bcfFileWrapper); + }, + error: (error) => { + this.notificationsService.error('Error during BCF import.'); + }, + }); + } + + newBcfFile(): void { + this.bcfFilesMessengerService.createNewBcfFile(); + } + + openSettings(): void { + this.matDialog.open(SettingsComponent, { + autoFocus: false, + width: '80%', + maxHeight: '70vh', + restoreFocus: false, + }); + } + + openDocumentation(): void { + this.backendService.openDocumentation(); + } + + saveBcfAs(): void { + this.bcfFilesMessengerService.saveCurrentActiveBcfFileAs(); + } + + private checkOpenedFileAndSendInfo(): void { + this.bcfFilesMessengerService.bcfFileSelected + .pipe(distinctUntilChanged(), takeUntil(this.destroyed$)) + .subscribe((bcfFile) => { + if (bcfFile.fileName) { + this.selectedProject$.pipe(take(1)).subscribe((project) => { + this.lastOpenedFilesClient + .setFileAsLastOpened(project?.id, bcfFile.fileName) + .subscribe(() => { + // Not doing anything with the response + }); + }); + } + }); + } + + showLastOpenedFiles(): void { + this.lastFileMenuOpened = true; + this.selectedProject$ + .pipe( + take(1), + switchMap((p) => { + return this.lastOpenedFilesClient.getLastOpenedFiles(p?.id); + }) + ) + .subscribe((f) => { + if (f.lastOpenedFiles.length === 0) { + this.notificationsService.info('No last opened files found.'); + } + this.lastOpenedFiles = [...f.lastOpenedFiles]; + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.html b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.html new file mode 100644 index 00000000..4dab01ce --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.html @@ -0,0 +1,103 @@ +
+ + Title + + + +
+
+ {{ topic.creationDate | date : "dd.MM.yyyy HH:mm" }} +
+ + + Status + + @for (status of (issueStatuses$ | async)?.values(); track status) { + {{ status }} + } + + + + + Type + + @for (type of (issueTypes$ | async)?.values(); track type) { + {{ type }} + } + + + + + Responsible + + @for (user of (users$ | async)?.values(); track user.id) { + {{ user.identifier }} + } + + + + + Due Date + + DD/MM/YYYY + + + +
+ + + Description + + + +
+

Viewpoints

+ +
+
+ +
+
+
+ +
+

Comments

+
+ +
+
+
diff --git a/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.scss b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.scss new file mode 100644 index 00000000..27659388 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.scss @@ -0,0 +1,21 @@ +.top-field { + width: 100%; +} + +.wrapper { + display: flex; + flex-direction: column; + gap: 6px; +} + +.info-select { + display: flex; + flex-direction: row; + gap: 12px; +} + +.full-width-button { + width: 100%; + margin-bottom: 8px; +} + diff --git a/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.spec.ts new file mode 100644 index 00000000..3c7aa0c2 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TopicDetailComponent } from './topic-detail.component'; + +describe('TopicDetailComponent', () => { + let component: TopicDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TopicDetailComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TopicDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.ts b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.ts new file mode 100644 index 00000000..147cc5c2 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/topic-detail/topic-detail.component.ts @@ -0,0 +1,157 @@ +import { + BcfFile, + BcfProjectExtensions, + BcfTopic, +} from '../../generated-client/generated-client'; +import { Component, Input, OnInit, inject } from '@angular/core'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { + MessageType, + TeamsMessengerService, +} from '../../services/teams-messenger.service'; + +import { AddStringValueComponent } from '../add-string-value/add-string-value.component'; +import { BackendService } from '../../services/BackendService'; +import { BcfFileAutomaticallySaveService } from '../../services/bcf-file-automaticaly-save.service'; +import { CommentsDetailComponent } from '../comments-detail/comments-detail.component'; +import { CommentsViewpointFilterPipe } from '../../pipes/comments-viewpoint-filter.pipe'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { IssueStatusesService } from '../../services/issue-statuses.service'; +import { IssueTypesService } from '../../services/issue-types.service'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { ProjectUsersService } from '../../services/project-users.service'; + +@Component({ + selector: 'bcfier-topic-detail', + standalone: true, + imports: [ + FormsModule, + MatIconModule, + MatCardModule, + MatButtonModule, + MatInputModule, + CommonModule, + MatSelectModule, + MatDialogModule, + AddStringValueComponent, + CommentsViewpointFilterPipe, + CommentsDetailComponent, + MatDatepickerModule, + ], + templateUrl: './topic-detail.component.html', + styleUrl: './topic-detail.component.scss', +}) +export class TopicDetailComponent implements OnInit { + @Input() topic!: BcfTopic; + @Input() bcfFile!: BcfFile; + issueStatusesService = inject(IssueStatusesService); + issueTypesService = inject(IssueTypesService); + users$ = inject(ProjectUsersService).users; + bcfFileAutomaticallySaveService = inject(BcfFileAutomaticallySaveService); + teamsMessengerService = inject(TeamsMessengerService); + extensions!: BcfProjectExtensions; + issueStatuses$ = this.issueStatusesService.issueStatuses; + issueTypes$ = this.issueTypesService.issueTypes; + isTitleChangeFirstTime = false; + defaultTopicTitle = 'New Issue'; + projectUsersService = inject(ProjectUsersService); + constructor( + private matDialog: MatDialog, + private backendService: BackendService + ) {} + + ngOnInit(): void { + if (this.bcfFile?.projectExtensions?.topicStatuses) { + this.issueStatusesService.setIssueStatuses( + this.bcfFile?.projectExtensions?.topicStatuses + ); + } + + if (this.bcfFile?.projectExtensions?.topicTypes) { + this.issueTypesService.setIssueTypes( + this.bcfFile?.projectExtensions?.topicTypes + ); + } + this.extensions = this.bcfFile?.projectExtensions || { + priorities: [], + snippetTypes: [], + topicLabels: [], + topicStatuses: ['Open', 'Closed', 'InProgress', 'ReOpened'], + topicTypes: [ + 'Info', + 'Issue', + 'Error', + 'Comment', + 'Request', + 'Structural', + ], + users: [], + }; + } + + addNewStatus(): void { + this.matDialog + .open(AddStringValueComponent, { + data: { + header: 'Status', + }, + }) + .afterClosed() + .subscribe((result) => { + if (result) { + this.extensions.topicStatuses.push(result); + this.topic.topicStatus = result; + } + }); + } + + addNewType(): void { + this.matDialog + .open(AddStringValueComponent, { + data: { + header: 'Topic Type', + }, + }) + .afterClosed() + .subscribe((result) => { + if (result) { + this.extensions.topicTypes.push(result); + this.topic.topicType = result; + } + }); + } + + addViewpoint(): void { + this.backendService.addViewpoint().subscribe((viewpoint) => { + if (viewpoint) { + this.topic.viewpoints.push(viewpoint); + this.teamsMessengerService.sendMessageToTeams(MessageType.AddViewpoint); + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + } + }); + } + + changeIssue(): void { + this.bcfFileAutomaticallySaveService.saveCurrentActiveBcfFileAutomatically(); + if (this.isTitleChangeFirstTime) { + this.teamsMessengerService.sendMessageToTeams(MessageType.ChangeTitle); + } + this.isTitleChangeFirstTime = false; + } + + checkIsTitleChangeFirstTime(e: string = ''): void { + if (e === this.defaultTopicTitle) { + this.isTitleChangeFirstTime = true; + } + } + + refreshUsers(): void { + this.projectUsersService.refreshUsers(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/components/users/users.component.html b/src/ipa-bcfier-ui/src/app/components/users/users.component.html new file mode 100644 index 00000000..e172b8d1 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/users/users.component.html @@ -0,0 +1,69 @@ +
+ + Filter + + + @if(shouldEnableProjectManagement) { + + } + + +
+ +
+ + + + + + + + + + + + + + + + + +
Name{{ row.identifier }} +
+ @if(shouldEnableProjectManagement) { + + delete + + } +
+
+ @if(filter) { + + No data matching the filter "{{ filter }}" + + } +
+ + +
diff --git a/src/ipa-bcfier-ui/src/app/components/users/users.component.scss b/src/ipa-bcfier-ui/src/app/components/users/users.component.scss new file mode 100644 index 00000000..2be343da --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/users/users.component.scss @@ -0,0 +1,40 @@ +.top-part { + display:flex; + justify-content: space-between; + align-items: top; + gap:20px; + + button { + margin-top: 8px; + } + + padding-right: 8px; +} + +.table-wrap { + max-height: 50vh; + overflow-y: auto; +} + +mat-form-field { + width: 100%; +} + +.mat-column-actions { + width: 100px; + text-align: end; +} + +mat-icon { + cursor: pointer; +} + +tr.project-row:hover { + background: whitesmoke; +} + +.action-btn-container { + display: flex; + gap: 5px; + align-items: center; +} diff --git a/src/ipa-bcfier-ui/src/app/components/users/users.component.spec.ts b/src/ipa-bcfier-ui/src/app/components/users/users.component.spec.ts new file mode 100644 index 00000000..fff471eb --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/users/users.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UsersComponent } from './users.component'; + +describe('UsersComponent', () => { + let component: UsersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [UsersComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(UsersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/components/users/users.component.ts b/src/ipa-bcfier-ui/src/app/components/users/users.component.ts new file mode 100644 index 00000000..2643231a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/components/users/users.component.ts @@ -0,0 +1,165 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + inject, +} from '@angular/core'; +import { AsyncPipe, CommonModule } from '@angular/common'; +import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { Subject, filter, switchMap, takeUntil } from 'rxjs'; +import { UserGet, UsersClient } from '../../generated-client/generated-client'; + +import { AddUserComponent } from '../add-user/add-user.component'; +import { AppConfigService } from '../../services/AppConfigService'; +import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { NotificationsService } from '../../services/notifications.service'; +import { SettingsMessengerService } from '../../services/settings-messenger.service'; +import { UsersService } from '../../services/light-query/users.service'; + +@Component({ + selector: 'bcfier-users', + standalone: true, + imports: [ + CommonModule, + MatFormFieldModule, + MatInputModule, + MatTableModule, + MatSortModule, + MatPaginatorModule, + AsyncPipe, + MatIconModule, + MatButtonModule, + FormsModule, + ], + templateUrl: './users.component.html', + styleUrl: './users.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class UsersComponent implements AfterViewInit, OnDestroy, OnInit { + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort!: MatSort; + + usersService = inject(UsersService); + usersClient = inject(UsersClient); + settingsMessengerService = inject(SettingsMessengerService); + notificationsService = inject(NotificationsService); + matDialog = inject(MatDialog); + cdr = inject(ChangeDetectorRef); + appConfigService = inject(AppConfigService); + + private destroyed$ = new Subject(); + dataSource!: MatTableDataSource; + displayedColumns = ['identifier', 'actions']; + filter = ''; + shouldEnableProjectManagement = + this.appConfigService.shouldEnableProjectManagementFeatures(); + + constructor() { + this.usersService + .connect() + .pipe(takeUntil(this.destroyed$)) + .subscribe((users) => { + this.dataSource = new MatTableDataSource(users); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + }); + } + + ngOnInit(): void { + this.usersService.onSort({ + active: 'identifier', + direction: 'desc', + }); + } + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + ngAfterViewInit() { + if (this.dataSource) { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + } + + applyFilter(filter: string) { + this.usersService.setQueryParameter('filter', filter.trim().toLowerCase()); + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } + + createUser(): void { + this.matDialog + .open(AddUserComponent, { + autoFocus: false, + restoreFocus: false, + width: '80%', + maxHeight: '70vh', + }) + .afterClosed() + .pipe( + filter((newProject) => !!newProject), + switchMap((newUserName: string) => { + return this.usersClient.createUser(newUserName); + }) + ) + .subscribe({ + next: () => { + this.usersService.forceRefresh(); + + if (this.filter) { + this.applyFilter(this.filter); + } + this.notificationsService.success('User added'); + }, + error: () => { + this.notificationsService.error('Failed to add user'); + }, + }); + } + + deleteUser(userId: string): void { + this.matDialog + .open(ConfirmDialogComponent, { + autoFocus: false, + restoreFocus: false, + data: 'delete this user', + }) + .afterClosed() + .pipe( + filter((confirm) => !!confirm), + switchMap(() => this.usersClient.deleteUser(userId)) + ) + .subscribe({ + next: () => { + this.notificationsService.success('User deleted'); + this.usersService.forceRefresh(); + if (this.filter) { + this.applyFilter(this.filter); + } + }, + error: () => { + this.notificationsService.error('Failed to delete user'); + }, + }); + } + + refresh(): void { + this.usersService.forceRefresh(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.spec.ts b/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.spec.ts new file mode 100644 index 00000000..f14ebb51 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.spec.ts @@ -0,0 +1,8 @@ +import { TopicPreviewImageDirective } from './topic-preview-image.directive'; + +describe('TopicPreviewImageDirective', () => { + it('should create an instance', () => { + const directive = new TopicPreviewImageDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.ts b/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.ts new file mode 100644 index 00000000..5d9f922b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/directives/topic-preview-image.directive.ts @@ -0,0 +1,49 @@ +import { + Directive, + ElementRef, + Input, + OnChanges, + OnInit, + SimpleChanges, +} from '@angular/core'; + +import { BcfTopic } from '../generated-client/generated-client'; + +@Directive({ + selector: '[bcfierTopicPreviewImage]', + standalone: true, +}) +export class TopicPreviewImageDirective implements OnInit, OnChanges { + @Input() bcfierTopicPreviewImage!: BcfTopic; + + constructor(private elementRef: ElementRef) {} + + ngOnInit(): void { + this.handleImage(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['bcfierTopicPreviewImage']) { + this.handleImage(); + } + } + + private handleImage(): void { + const viewpoints = this.bcfierTopicPreviewImage.viewpoints.filter( + (vp) => vp.snapshotBase64 + ); + + if (viewpoints.length === 0) { + this.elementRef.nativeElement.style.display = 'none'; + return; + } + + this.elementRef.nativeElement.style.display = null; + + // We're using the base64 data from the snapshot to + // generate a base64 data url with png type + const imageUrl = `data:image/png;base64,${viewpoints[0].snapshotBase64}`; + // Then we're appending it to the host element as src attribute + this.elementRef.nativeElement.src = imageUrl; + } +} diff --git a/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.spec.ts b/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.spec.ts new file mode 100644 index 00000000..6a0bb879 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.spec.ts @@ -0,0 +1,8 @@ +import { ViewpointImageDirective } from './viewpoint-image.directive'; + +describe('ViewpointImageDirective', () => { + it('should create an instance', () => { + const directive = new ViewpointImageDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.ts b/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.ts new file mode 100644 index 00000000..02d7ba58 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/directives/viewpoint-image.directive.ts @@ -0,0 +1,38 @@ +import { Directive, ElementRef, Input, SimpleChanges } from '@angular/core'; + +import { BcfViewpoint } from '../generated-client/generated-client'; + +@Directive({ + selector: '[bcfierViewpointImage]', + standalone: true, +}) +export class ViewpointImageDirective { + @Input() bcfierViewpointImage: BcfViewpoint | null = null; + + constructor(private elementRef: ElementRef) {} + + ngOnInit(): void { + this.handleImage(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes['bcfierViewpointImage']) { + this.handleImage(); + } + } + + private handleImage(): void { + if (!this.bcfierViewpointImage?.snapshotBase64) { + this.elementRef.nativeElement.style.display = 'none'; + return; + } + + this.elementRef.nativeElement.style.display = null; + + // We're using the base64 data from the snapshot to + // generate a base64 data url with png type + const imageUrl = `data:image/png;base64,${this.bcfierViewpointImage.snapshotBase64}`; + // Then we're appending it to the host element as src attribute + this.elementRef.nativeElement.src = imageUrl; + } +} diff --git a/src/ipa-bcfier-ui/src/app/functions/uuid.ts b/src/ipa-bcfier-ui/src/app/functions/uuid.ts new file mode 100644 index 00000000..4b4f0277 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/functions/uuid.ts @@ -0,0 +1,9 @@ +import { v4 as uuidv4 } from 'uuid'; + +export function getNewRandomGuid(): string { + if (crypto && crypto.randomUUID) { + return crypto.randomUUID(); + } + + return uuidv4(); +} diff --git a/src/ipa-bcfier-ui/src/app/generated-client/generated-client.ts b/src/ipa-bcfier-ui/src/app/generated-client/generated-client.ts new file mode 100644 index 00000000..eebaf5b5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/generated-client/generated-client.ts @@ -0,0 +1,2163 @@ +//---------------------- +// +// Generated using the NSwag toolchain v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +/* tslint:disable */ +/* eslint-disable */ +// ReSharper disable InconsistentNaming + +import { mergeMap as _observableMergeMap, catchError as _observableCatch } from 'rxjs/operators'; +import { Observable, throwError as _observableThrow, of as _observableOf } from 'rxjs'; +import { Injectable, Inject, Optional, InjectionToken } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpResponse, HttpResponseBase } from '@angular/common/http'; + +export const API_BASE_URL = new InjectionToken('API_BASE_URL'); + +export interface IBcfConversionClient { + importBcfFile(filePath: string | null | undefined): Observable; + exportBcfFile(projectId: string | null | undefined, bcfFile: BcfFile): Observable; + saveBcfFile(bcfFileWrapper: BcfFileWrapper): Observable; + mergeBcfFiles(): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class BcfConversionClient implements IBcfConversionClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + importBcfFile(filePath: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/bcf-conversion/import?"; + if (filePath !== undefined && filePath !== null) + url_ += "filePath=" + encodeURIComponent("" + filePath) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processImportBcfFile(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processImportBcfFile(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processImportBcfFile(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as BcfFileWrapper; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + exportBcfFile(projectId: string | null | undefined, bcfFile: BcfFile): Observable { + let url_ = this.baseUrl + "/api/bcf-conversion/export?"; + if (projectId !== undefined && projectId !== null) + url_ += "projectId=" + encodeURIComponent("" + projectId) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(bcfFile); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processExportBcfFile(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processExportBcfFile(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processExportBcfFile(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as BcfFileWrapper; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + saveBcfFile(bcfFileWrapper: BcfFileWrapper): Observable { + let url_ = this.baseUrl + "/api/bcf-conversion/save"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(bcfFileWrapper); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processSaveBcfFile(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processSaveBcfFile(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processSaveBcfFile(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + mergeBcfFiles(): Observable { + let url_ = this.baseUrl + "/api/bcf-conversion/merge"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processMergeBcfFiles(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processMergeBcfFiles(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processMergeBcfFiles(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as BcfFile; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IDocumentationClient { + openDocumentation(): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class DocumentationClient implements IDocumentationClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + openDocumentation(): Observable { + let url_ = this.baseUrl + "/api/documentation"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processOpenDocumentation(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processOpenDocumentation(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processOpenDocumentation(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IFrontendConfigClient { + getFrontendConfigAsJavaScript(timestamp: string | null | undefined): Observable; + getFrontendConfig(timestamp: string | null | undefined): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class FrontendConfigClient implements IFrontendConfigClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getFrontendConfigAsJavaScript(timestamp: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/frontend-config/config.js?"; + if (timestamp !== undefined && timestamp !== null) + url_ += "timestamp=" + encodeURIComponent("" + timestamp) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/octet-stream" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetFrontendConfigAsJavaScript(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetFrontendConfigAsJavaScript(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetFrontendConfigAsJavaScript(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return _observableOf({ fileName: fileName, data: responseBlob as any, status: status, headers: _headers }); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + getFrontendConfig(timestamp: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/frontend-config/json?"; + if (timestamp !== undefined && timestamp !== null) + url_ += "timestamp=" + encodeURIComponent("" + timestamp) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetFrontendConfig(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetFrontendConfig(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetFrontendConfig(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as FrontendConfig; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface ILastOpenedFilesClient { + getLastOpenedFiles(projectId: string | null | undefined): Observable; + setFileAsLastOpened(projectId: string | null | undefined, filePath: string | undefined): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class LastOpenedFilesClient implements ILastOpenedFilesClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getLastOpenedFiles(projectId: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/last-opened-files?"; + if (projectId !== undefined && projectId !== null) + url_ += "projectId=" + encodeURIComponent("" + projectId) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetLastOpenedFiles(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetLastOpenedFiles(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetLastOpenedFiles(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as LastOpenedFilesWrapperGet; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + setFileAsLastOpened(projectId: string | null | undefined, filePath: string | undefined): Observable { + let url_ = this.baseUrl + "/api/last-opened-files?"; + if (projectId !== undefined && projectId !== null) + url_ += "projectId=" + encodeURIComponent("" + projectId) + "&"; + if (filePath === null) + throw new Error("The parameter 'filePath' cannot be null."); + else if (filePath !== undefined) + url_ += "filePath=" + encodeURIComponent("" + filePath) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("put", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processSetFileAsLastOpened(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processSetFileAsLastOpened(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processSetFileAsLastOpened(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IProjectsClient { + getAllProjects(filter: string | null | undefined, revitPathFilter: string | null | undefined): Observable; + createProject(model: ProjectPost): Observable; + editProject(projectId: string, model: ProjectPut): Observable; + deleteProject(projectId: string): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class ProjectsClient implements IProjectsClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getAllProjects(filter: string | null | undefined, revitPathFilter: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/projects?"; + if (filter !== undefined && filter !== null) + url_ += "filter=" + encodeURIComponent("" + filter) + "&"; + if (revitPathFilter !== undefined && revitPathFilter !== null) + url_ += "revitPathFilter=" + encodeURIComponent("" + revitPathFilter) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetAllProjects(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetAllProjects(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetAllProjects(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as PaginationResultOfProjectGet; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + createProject(model: ProjectPost): Observable { + let url_ = this.baseUrl + "/api/projects"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(model); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCreateProject(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCreateProject(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processCreateProject(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProjectGet; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + editProject(projectId: string, model: ProjectPut): Observable { + let url_ = this.baseUrl + "/api/projects/{projectId}"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(model); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("put", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processEditProject(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processEditProject(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processEditProject(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProjectGet; + return _observableOf(result200); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + deleteProject(projectId: string): Observable { + let url_ = this.baseUrl + "/api/projects/{projectId}"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("delete", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processDeleteProject(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processDeleteProject(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processDeleteProject(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IProjectUsersClient { + getProjectUsersForProject(projectId: string): Observable; + addUserToProject(projectId: string, model: ProjectUserPost): Observable; + deleteProjectUser(projectId: string, projectUserId: string): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class ProjectUsersClient implements IProjectUsersClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getProjectUsersForProject(projectId: string): Observable { + let url_ = this.baseUrl + "/api/projects/{projectId}"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetProjectUsersForProject(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetProjectUsersForProject(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetProjectUsersForProject(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProjectUserGet[]; + return _observableOf(result200); + })); + } else if (status === 404) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result404: any = null; + result404 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProblemDetails; + return throwException("A server side error occurred.", status, _responseText, _headers, result404); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + addUserToProject(projectId: string, model: ProjectUserPost): Observable { + let url_ = this.baseUrl + "/api/projects/{projectId}"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(model); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processAddUserToProject(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processAddUserToProject(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processAddUserToProject(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProjectUserGet[]; + return _observableOf(result200); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 404) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result404: any = null; + result404 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProblemDetails; + return throwException("A server side error occurred.", status, _responseText, _headers, result404); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + deleteProjectUser(projectId: string, projectUserId: string): Observable { + let url_ = this.baseUrl + "/api/projects/{projectId}/{projectUserId}"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + if (projectUserId === undefined || projectUserId === null) + throw new Error("The parameter 'projectUserId' must be defined."); + url_ = url_.replace("{projectUserId}", encodeURIComponent("" + projectUserId)); + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("delete", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processDeleteProjectUser(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processDeleteProjectUser(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processDeleteProjectUser(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProjectUserGet[]; + return _observableOf(result200); + })); + } else if (status === 404) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result404: any = null; + result404 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ProblemDetails; + return throwException("A server side error occurred.", status, _responseText, _headers, result404); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface ISettingsClient { + getSettings(): Observable; + saveSettings(settings: Settings): Observable; + choseMainDatabaseLocation(): Observable; + getIsAlwaysOnTop(): Observable; + setIsAlwaysOnTop(isAlwaysOnTop: boolean | undefined): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class SettingsClient implements ISettingsClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getSettings(): Observable { + let url_ = this.baseUrl + "/api/settings"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetSettings(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetSettings(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetSettings(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as Settings; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + saveSettings(settings: Settings): Observable { + let url_ = this.baseUrl + "/api/settings"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(settings); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + }) + }; + + return this.http.request("put", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processSaveSettings(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processSaveSettings(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processSaveSettings(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + choseMainDatabaseLocation(): Observable { + let url_ = this.baseUrl + "/api/settings/database-location"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processChoseMainDatabaseLocation(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processChoseMainDatabaseLocation(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processChoseMainDatabaseLocation(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + getIsAlwaysOnTop(): Observable { + let url_ = this.baseUrl + "/api/settings/always-on-top"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetIsAlwaysOnTop(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetIsAlwaysOnTop(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetIsAlwaysOnTop(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as boolean; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + setIsAlwaysOnTop(isAlwaysOnTop: boolean | undefined): Observable { + let url_ = this.baseUrl + "/api/settings/always-on-top?"; + if (isAlwaysOnTop === null) + throw new Error("The parameter 'isAlwaysOnTop' cannot be null."); + else if (isAlwaysOnTop !== undefined) + url_ += "isAlwaysOnTop=" + encodeURIComponent("" + isAlwaysOnTop) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("put", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processSetIsAlwaysOnTop(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processSetIsAlwaysOnTop(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processSetIsAlwaysOnTop(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface ITeamsMessagesClient { + announceNewCommentInProjectTopic(projectId: string, topicId: string, model: TeamsMessagePost): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class TeamsMessagesClient implements ITeamsMessagesClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + announceNewCommentInProjectTopic(projectId: string, topicId: string, model: TeamsMessagePost): Observable { + let url_ = this.baseUrl + "/api/teams-messages/projects/{projectId}/topics/{topicId}/comments"; + if (projectId === undefined || projectId === null) + throw new Error("The parameter 'projectId' must be defined."); + url_ = url_.replace("{projectId}", encodeURIComponent("" + projectId)); + if (topicId === undefined || topicId === null) + throw new Error("The parameter 'topicId' must be defined."); + url_ = url_.replace("{topicId}", encodeURIComponent("" + topicId)); + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(model); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processAnnounceNewCommentInProjectTopic(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processAnnounceNewCommentInProjectTopic(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processAnnounceNewCommentInProjectTopic(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IUsersClient { + getUsers(filter: string | null | undefined): Observable; + createUser(userName: string | undefined): Observable; + getAllUsers(): Observable; + deleteUser(userId: string): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class UsersClient implements IUsersClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + getUsers(filter: string | null | undefined): Observable { + let url_ = this.baseUrl + "/api/users?"; + if (filter !== undefined && filter !== null) + url_ += "filter=" + encodeURIComponent("" + filter) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetUsers(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetUsers(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetUsers(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as UserGet[]; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + createUser(userName: string | undefined): Observable { + let url_ = this.baseUrl + "/api/users?"; + if (userName === null) + throw new Error("The parameter 'userName' cannot be null."); + else if (userName !== undefined) + url_ += "userName=" + encodeURIComponent("" + userName) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCreateUser(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCreateUser(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processCreateUser(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as UserGet; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + getAllUsers(): Observable { + let url_ = this.baseUrl + "/api/users/all"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetAllUsers(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetAllUsers(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetAllUsers(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as UserGet[]; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + deleteUser(userId: string): Observable { + let url_ = this.baseUrl + "/api/users/{userId}"; + if (userId === undefined || userId === null) + throw new Error("The parameter 'userId' must be defined."); + url_ = url_.replace("{userId}", encodeURIComponent("" + userId)); + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("delete", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processDeleteUser(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processDeleteUser(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processDeleteUser(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +export interface IViewpointsClient { + showViewpoint(viewpoint: BcfViewpoint): Observable; + createViewpoint(): Observable; + getAvailableNavisworksClashes(): Observable; + createNavisworksClashDetectionResultIssues(model: NavisworksClashCreationData): Observable; + cancelNavisworksClashDetection(clashId: string): Observable; +} + +@Injectable({ + providedIn: 'root' +}) +export class ViewpointsClient implements IViewpointsClient { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ?? ""; + } + + showViewpoint(viewpoint: BcfViewpoint): Observable { + let url_ = this.baseUrl + "/api/viewpoints/visualization"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(viewpoint); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processShowViewpoint(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processShowViewpoint(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processShowViewpoint(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + createViewpoint(): Observable { + let url_ = this.baseUrl + "/api/viewpoints"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCreateViewpoint(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCreateViewpoint(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processCreateViewpoint(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as BcfViewpoint; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + getAvailableNavisworksClashes(): Observable { + let url_ = this.baseUrl + "/api/viewpoints/navisworks-clashes"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetAvailableNavisworksClashes(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetAvailableNavisworksClashes(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processGetAvailableNavisworksClashes(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as NavisworksClashSelection[]; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + createNavisworksClashDetectionResultIssues(model: NavisworksClashCreationData): Observable { + let url_ = this.baseUrl + "/api/viewpoints/navisworks-clashes"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(model); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCreateNavisworksClashDetectionResultIssues(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCreateNavisworksClashDetectionResultIssues(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processCreateNavisworksClashDetectionResultIssues(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result200: any = null; + result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as BcfTopic[]; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } + + cancelNavisworksClashDetection(clashId: string): Observable { + let url_ = this.baseUrl + "/api/viewpoints/navisworks-clashes/{clashId}"; + if (clashId === undefined || clashId === null) + throw new Error("The parameter 'clashId' must be defined."); + url_ = url_.replace("{clashId}", encodeURIComponent("" + clashId)); + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + }) + }; + + return this.http.request("delete", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCancelNavisworksClashDetection(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCancelNavisworksClashDetection(response_ as any); + } catch (e) { + return _observableThrow(e) as any as Observable; + } + } else + return _observableThrow(response_) as any as Observable; + })); + } + + protected processCancelNavisworksClashDetection(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response as any).error instanceof Blob ? (response as any).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }} + if (status === 400) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + let result400: any = null; + result400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as ApiError; + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + })); + } else if (status === 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return _observableOf(null as any); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap((_responseText: string) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null as any); + } +} + +/** Data transfer class to convey api errors */ +export interface ApiError { + /** This dictionary contains a set of all errors and their messages */ + errors?: { [key: string]: string[]; } | null; +} + +export interface BcfFileWrapper { + fileName: string; + bcfFile?: BcfFile | null; +} + +export interface BcfFile { + fileName: string; + project?: BcfProject; + fileAttachments?: BcfFileAttachment[]; + projectExtensions?: BcfProjectExtensions; + topics: BcfTopic[]; +} + +export interface BcfProject { + id?: string; + name?: string; +} + +export interface BcfFileAttachment { + name: string; + base64Data?: string; +} + +export interface BcfProjectExtensions { + users: string[]; + topicLabels: string[]; + topicTypes: string[]; + priorities: string[]; + snippetTypes: string[]; + topicStatuses: string[]; +} + +export interface BcfTopic { + id: string; + files: BcfTopicFile[]; + viewpoints: BcfViewpoint[]; + documentReferences: BcfDocumentReference[]; + comments: BcfComment[]; + assignedTo?: string; + creationAuthor?: string; + creationDate?: Date | null; + description?: string; + modifiedAuthor?: string; + modifiedDate?: Date | null; + serverAssignedId?: string; + topicStatus?: string; + title?: string; + stage?: string; + priority?: string; + topicType?: string; + dueDate?: Date | null; + index?: number; + labels: string[]; + relatedTopicIds: string[]; + referenceLinks: string[]; +} + +export interface BcfTopicFile { + fileName: string; + referenceLink?: string; + ifcProjectId?: string; + ifcSpatialStructureElementId?: string; + date?: Date | null; +} + +export interface BcfViewpoint { + id: string; + clippingPlanes: BcfViewpointClippingPlane[]; + lines: BcfViewpointLine[]; + snapshotBase64?: string; + orthogonalCamera?: BcfViewpointOrthogonalCamera | null; + perspectiveCamera?: BcfViewpointPerspectiveCamera | null; + viewpointComponents: BcfViewpointComponents; +} + +export interface BcfViewpointClippingPlane { + location: BcfViewpointPoint; + direction: BcfViewpointVector; +} + +export interface BcfViewpointPoint { + x: number; + y: number; + z: number; +} + +export interface BcfViewpointVector { + x: number; + y: number; + z: number; +} + +export interface BcfViewpointLine { + startPoint: BcfViewpointPoint; + endPoint: BcfViewpointPoint; +} + +export interface BcfViewpointCameraBase { + aspectRatio: number; + direction: BcfViewpointVector; + upVector: BcfViewpointVector; + viewPoint: BcfViewpointPoint; +} + +export interface BcfViewpointOrthogonalCamera extends BcfViewpointCameraBase { + viewToWorldScale: number; +} + +export interface BcfViewpointPerspectiveCamera extends BcfViewpointCameraBase { + fieldOfView: number; +} + +export interface BcfViewpointComponents { + coloring: BcfViewpointComponentColoring[]; + selectedComponents: BcfViewpointComponent[]; + visibility: BcfViewpointComponentVisibility; +} + +export interface BcfViewpointComponentColoring { + color: string; + components: BcfViewpointComponent[]; +} + +export interface BcfViewpointComponent { + originatingSystem?: string; + authoringToolId?: string; + ifcGuid: string; +} + +export interface BcfViewpointComponentVisibility { + defaultVisibility: boolean; + exceptions: BcfViewpointComponent[]; +} + +export interface BcfDocumentReference { + id: string; + url?: string; + documentId?: string; + description?: string; +} + +export interface BcfComment { + id: string; + text?: string; + author?: string; + creationDate?: Date | null; + modifiedBy?: string; + modifiedDate?: Date | null; + viewpointId?: string | null; +} + +export interface FrontendConfig { + isInElectronMode: boolean; + isConnectedToRevit: boolean; + isConnectedToNavisworks: boolean; + revitProjectPath?: string | null; + environment: string; + cadPluginVersion?: string | null; +} + +export interface LastOpenedFilesWrapperGet { + lastOpenedFiles: LastOpenedFileGet[]; +} + +export interface LastOpenedFileGet { + fileName: string; + openedAtUtc: Date; +} + +export interface PaginationResultOfProjectGet { + page?: number; + pageSize?: number; + totalCount?: number; + data?: ProjectGet[] | null; +} + +export interface ProjectGet { + id: string; + name: string; + createdAtUtc: Date; + revitIdentifier?: string | null; + teamsWebhook?: string | null; +} + +export interface ProjectPost { + name: string; + revitIdentifier?: string | null; + teamsWebhook?: string | null; +} + +export interface ProjectPut { + id: string; + name: string; + revitIdentifier?: string | null; + teamsWebhook?: string | null; +} + +export interface ProjectUserGet { + id: string; + identifier: string; +} + +export interface ProblemDetails { + type?: string | null; + title?: string | null; + status?: number | null; + detail?: string | null; + instance?: string | null; + + [key: string]: any; +} + +export interface ProjectUserPost { + userId?: string | null; + identifier?: string | null; +} + +export interface Settings { + username: string; + mainDatabaseLocation?: string | null; +} + +export interface TeamsMessagePost { + topicTitle?: string | null; + comment?: string | null; + viewpointBase64?: string | null; + username: string; +} + +export interface UserGet { + id?: string; + identifier: string; +} + +export interface NavisworksClashSelection { + id?: string; + displayName?: string; + isGroup?: boolean; +} + +export interface NavisworksClashCreationData { + clashId?: string; + status?: string | null; + excludedClashIds?: string[]; + shouldMoveBoundingBoxToCenterOfClash?: boolean; +} + +export interface FileResponse { + data: Blob; + status: number; + fileName?: string; + headers?: { [name: string]: any }; +} + +export class SwaggerException extends Error { + override message: string; + status: number; + response: string; + headers: { [key: string]: any; }; + result: any; + + constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) { + super(); + + this.message = message; + this.status = status; + this.response = response; + this.headers = headers; + this.result = result; + } + + protected isSwaggerException = true; + + static isSwaggerException(obj: any): obj is SwaggerException { + return obj.isSwaggerException === true; + } +} + +function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): Observable { + if (result !== null && result !== undefined) + return _observableThrow(result); + else + return _observableThrow(new SwaggerException(message, status, response, headers, null)); +} + +function blobToText(blob: any): Observable { + return new Observable((observer: any) => { + if (!blob) { + observer.next(""); + observer.complete(); + } else { + let reader = new FileReader(); + reader.onload = event => { + observer.next((event.target as any).result); + observer.complete(); + }; + reader.readAsText(blob); + } + }); +} \ No newline at end of file diff --git a/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.spec.ts b/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.spec.ts new file mode 100644 index 00000000..0e924f72 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.spec.ts @@ -0,0 +1,8 @@ +import { CommentsViewpointFilterPipe } from './comments-viewpoint-filter.pipe'; + +describe('CommentsViewpointFilterPipe', () => { + it('create an instance', () => { + const pipe = new CommentsViewpointFilterPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.ts b/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.ts new file mode 100644 index 00000000..82db2be0 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/comments-viewpoint-filter.pipe.ts @@ -0,0 +1,25 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import { BcfComment } from '../generated-client/generated-client'; + +@Pipe({ + name: 'commentsViewpointFilter', + standalone: true, +}) +export class CommentsViewpointFilterPipe implements PipeTransform { + transform( + value: BcfComment[], + viewpointId?: string, + showAll?: boolean + ): BcfComment[] { + if (showAll === true) { + return value; + } + + const filteredComments = value.filter((comment) => + viewpointId ? comment.viewpointId === viewpointId : !comment.viewpointId + ); + + return filteredComments; + } +} diff --git a/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.spec.ts b/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.spec.ts new file mode 100644 index 00000000..e3962dee --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.spec.ts @@ -0,0 +1,8 @@ +import { FileNamePipe } from './file-name.pipe'; + +describe('FileNamePipe', () => { + it('create an instance', () => { + const pipe = new FileNamePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.ts b/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.ts new file mode 100644 index 00000000..c5c3044a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/file-name.pipe.ts @@ -0,0 +1,15 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'fileName', + standalone: true, +}) +export class FileNamePipe implements PipeTransform { + transform(value?: string | null): string | null { + if (!value) { + return null; + } + + return value.replace(/^.*[\\/]/, ''); + } +} diff --git a/src/ipa-bcfier-ui/src/app/pipes/safe-url.pipe.ts b/src/ipa-bcfier-ui/src/app/pipes/safe-url.pipe.ts new file mode 100644 index 00000000..fab417fd --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/safe-url.pipe.ts @@ -0,0 +1,36 @@ +import { Pipe, type PipeTransform } from '@angular/core'; +import { + DomSanitizer, + SafeHtml, + SafeResourceUrl, + SafeScript, + SafeStyle, + SafeUrl, +} from '@angular/platform-browser'; + +@Pipe({ + name: 'bcfierSafeUrl', + standalone: true, +}) +export class SafeUrlPipe implements PipeTransform { + constructor(protected _sanitizer: DomSanitizer) {} + transform( + value: string, + type: string + ): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl { + switch (type) { + case 'html': + return this._sanitizer.bypassSecurityTrustHtml(value); + case 'style': + return this._sanitizer.bypassSecurityTrustStyle(value); + case 'script': + return this._sanitizer.bypassSecurityTrustScript(value); + case 'url': + return this._sanitizer.bypassSecurityTrustUrl(value); + case 'resourceUrl': + return this._sanitizer.bypassSecurityTrustResourceUrl(value); + default: + return this._sanitizer.bypassSecurityTrustHtml(value); + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.spec.ts b/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.spec.ts new file mode 100644 index 00000000..7318dd88 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.spec.ts @@ -0,0 +1,8 @@ +import { TopicFilterPipe } from './topic-filter.pipe'; + +describe('TopicFilterPipe', () => { + it('create an instance', () => { + const pipe = new TopicFilterPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.ts b/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.ts new file mode 100644 index 00000000..b10ec0a0 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/pipes/topic-filter.pipe.ts @@ -0,0 +1,33 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import { BcfTopic } from '../generated-client/generated-client'; + +@Pipe({ + name: 'topicFilter', + standalone: true, +}) +export class TopicFilterPipe implements PipeTransform { + transform(value: BcfTopic[], filter: string): BcfTopic[] { + if (!filter) { + return value; + } + + return value.filter((topic) => { + if ( + topic.title != null && + topic.title.toUpperCase().indexOf(filter.toUpperCase()) !== -1 + ) { + return true; + } + + if ( + topic.description != null && + topic.description.toUpperCase().indexOf(filter.toUpperCase()) !== -1 + ) { + return true; + } + + return false; + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/AppConfigService.ts b/src/ipa-bcfier-ui/src/app/services/AppConfigService.ts new file mode 100644 index 00000000..254c86c5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/AppConfigService.ts @@ -0,0 +1,28 @@ +import { FrontendConfig } from '../generated-client/generated-client'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class AppConfigService { + private defaultFrontendConfig: FrontendConfig = { + isInElectronMode: false, + isConnectedToRevit: false, + isConnectedToNavisworks: false, + environment: 'Production', + }; + + getFrontendConfig(): FrontendConfig { + return ( + ((window as any)['ipaBcfierFrontendConfig'] as FrontendConfig) || + this.defaultFrontendConfig + ); + } + + shouldEnableProjectManagementFeatures(): boolean { + return ( + !this.getFrontendConfig().isConnectedToNavisworks && + !this.getFrontendConfig().isConnectedToRevit + ); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/BackendService.ts b/src/ipa-bcfier-ui/src/app/services/BackendService.ts new file mode 100644 index 00000000..af553b7e --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/BackendService.ts @@ -0,0 +1,123 @@ +import { + BcfConversionClient, + BcfFileWrapper, + BcfViewpoint, + DocumentationClient, + Settings, + SettingsClient, + ViewpointsClient, +} from '../generated-client/generated-client'; +import { Observable, Subject, catchError, of, tap } from 'rxjs'; + +import { AddSnapshotViewpointComponent } from '../components/add-snapshot-viewpoint/add-snapshot-viewpoint.component'; +import { AppConfigService } from './AppConfigService'; +import { Injectable } from '@angular/core'; +import { LoadingService } from './loading.service'; +import { MatDialog } from '@angular/material/dialog'; +import { NotificationsService } from './notifications.service'; +import { SelectedProjectMessengerService } from './selected-project-messenger.service'; + +@Injectable({ + providedIn: 'root', +}) +export class BackendService { + constructor( + private matDialog: MatDialog, + private appConfigService: AppConfigService, + private loadingService: LoadingService, + private notificationsService: NotificationsService, + private bcfConversionClient: BcfConversionClient, + private documentationClient: DocumentationClient, + private settingsClient: SettingsClient, + private viewpointsClient: ViewpointsClient, + selectedProjectMessengerService: SelectedProjectMessengerService + ) { + selectedProjectMessengerService.selectedProject.subscribe((p) => { + this.selectedProjectId = p?.id || null; + }); + } + + private selectedProjectId: string | null = null; + + importBcfFile(fileName?: string): Observable { + return this.bcfConversionClient.importBcfFile(fileName); + } + + exportBcfFile(bcfFile: BcfFileWrapper): Observable { + return this.bcfConversionClient.exportBcfFile( + this.selectedProjectId, + bcfFile.bcfFile! + ); + } + + saveBcfFile(bcfFileWrapper: BcfFileWrapper): Observable { + return this.bcfConversionClient.saveBcfFile(bcfFileWrapper); + } + + openDocumentation(): void { + this.documentationClient.openDocumentation().subscribe(() => { + /* Not doing anything with the result */ + }); + } + + getSettings(): Observable { + return this.settingsClient.getSettings(); + } + + saveSettings(settings: Settings): Observable { + return this.settingsClient.saveSettings(settings); + } + + addViewpoint(): Observable { + if ( + this.appConfigService.getFrontendConfig().isConnectedToRevit || + this.appConfigService.getFrontendConfig().isConnectedToNavisworks + ) { + this.loadingService.showLoadingScreen(); + + return this.viewpointsClient.createViewpoint().pipe( + tap(() => this.loadingService.hideLoadingScreen()), + catchError(() => { + this.loadingService.hideLoadingScreen(); + this.notificationsService.error('Failed to add viewpoint.'); + return of(null); + }) + ); + } else { + const subject = new Subject(); + this.matDialog + .open(AddSnapshotViewpointComponent) + .afterClosed() + .subscribe((viewpoint) => { + if (viewpoint) { + subject.next(viewpoint); + } else { + subject.next(null); + } + setTimeout(() => { + subject.complete(); + }, 0); + }); + + return subject.asObservable(); + } + } + + selectViewpoint(viewpoint: BcfViewpoint): void { + if ( + this.appConfigService.getFrontendConfig().isConnectedToRevit || + this.appConfigService.getFrontendConfig().isConnectedToNavisworks + ) { + this.loadingService.showLoadingScreen(); + this.viewpointsClient.showViewpoint(viewpoint).subscribe({ + next: () => this.loadingService.hideLoadingScreen(), + error: () => { + this.loadingService.hideLoadingScreen(); + this.notificationsService.error('Failed to select viewpoint.'); + }, + }); + } else { + // Not doing anything in the standalone version + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/bcf-file-automaticaly-save.service.ts b/src/ipa-bcfier-ui/src/app/services/bcf-file-automaticaly-save.service.ts new file mode 100644 index 00000000..889ebf3c --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/bcf-file-automaticaly-save.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class BcfFileAutomaticallySaveService { + private bcfFileSaveAutomaticallyRequestedSource = new Subject(); + bcfFileSaveAutomaticallyRequested = + this.bcfFileSaveAutomaticallyRequestedSource.asObservable(); + + constructor() {} + + saveCurrentActiveBcfFileAutomatically(): void { + this.bcfFileSaveAutomaticallyRequestedSource.next(); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.spec.ts new file mode 100644 index 00000000..a7a69181 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BcfFilesMessengerService } from './bcf-files-messenger.service'; + +describe('BcfFilesMessengerService', () => { + let service: BcfFilesMessengerService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BcfFilesMessengerService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.ts new file mode 100644 index 00000000..b09a2bab --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/bcf-files-messenger.service.ts @@ -0,0 +1,73 @@ +import { BcfFile, BcfFileWrapper } from '../generated-client/generated-client'; +import { ReplaySubject, Subject } from 'rxjs'; + +import { Injectable } from '@angular/core'; +import { getNewRandomGuid } from '../functions/uuid'; + +@Injectable({ + providedIn: 'root', +}) +export class BcfFilesMessengerService { + private bcfFilesSubject: ReplaySubject = new ReplaySubject< + BcfFileWrapper[] + >(1); + public bcfFiles = this.bcfFilesSubject.asObservable(); + private currentBcfFiles: BcfFileWrapper[] = []; + + private bcfFileSaveAsRequestedSource = new Subject(); + bcfFileSaveAsRequested = this.bcfFileSaveAsRequestedSource.asObservable(); + + private bcfFileSelectedSource = new ReplaySubject(1); + bcfFileSelected = this.bcfFileSelectedSource.asObservable(); + + setBcfFileSelected(bcfFileSelected: BcfFileWrapper): void { + this.bcfFileSelectedSource.next(bcfFileSelected); + } + constructor() { + // We're initializing with an empty array just so other parts of the app + // that depend on loading the list of files initially get an empty list + this.bcfFilesSubject.next([]); + } + + createNewBcfFile(): void { + const bcfFile: BcfFileWrapper = { + fileName: '', + bcfFile: { + fileName: 'issues.bcf', + topics: [], + fileAttachments: [], + project: { + id: getNewRandomGuid(), + }, + projectExtensions: { + priorities: [], + snippetTypes: [], + topicLabels: [], + topicStatuses: [], + topicTypes: [], + users: [], + }, + }, + }; + this.currentBcfFiles.push(bcfFile); + this.bcfFilesSubject.next(this.currentBcfFiles); + this.bcfFileSelectedSource.next(bcfFile); + } + + saveCurrentActiveBcfFileAs(): void { + this.bcfFileSaveAsRequestedSource.next(); + } + + openBcfFile(bcfFileWrapper: BcfFileWrapper) { + this.currentBcfFiles.push(bcfFileWrapper); + this.bcfFilesSubject.next(this.currentBcfFiles); + this.bcfFileSelectedSource.next(bcfFileWrapper); + } + + closeBcfFile(bcfFile: BcfFile) { + this.currentBcfFiles = this.currentBcfFiles.filter( + (f) => f.bcfFile !== bcfFile + ); + this.bcfFilesSubject.next(this.currentBcfFiles); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.spec.ts new file mode 100644 index 00000000..28d91f19 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BcfierHubConnectorService } from './bcfier-hub-connector.service'; + +describe('BcfierHubConnectorService', () => { + let service: BcfierHubConnectorService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BcfierHubConnectorService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.ts b/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.ts new file mode 100644 index 00000000..6e5ef904 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/connectors/bcfier-hub-connector.service.ts @@ -0,0 +1,76 @@ +import { + HubConnection, + HubConnectionBuilder, + HubConnectionState, +} from '@microsoft/signalr'; +import { Injectable, NgZone } from '@angular/core'; + +import { CadErrorDialogComponent } from '../../components/cad-error-dialog/cad-error-dialog.component'; +import { LoadingService } from '../loading.service'; +import { MatDialog } from '@angular/material/dialog'; +import { NavisworksClashProgressMessengerService } from '../messengers/navisworks-clash-progress-messenger.service'; +import { NotificationsService } from '../notifications.service'; + +@Injectable({ + providedIn: 'root', +}) +export class BcfierHubConnectorService { + private connection: HubConnection; + + constructor( + private notificationsService: NotificationsService, + private ngZone: NgZone, + private loadingService: LoadingService, + private matDialog: MatDialog, + private navisworksClashProgressMessengerService: NavisworksClashProgressMessengerService + ) { + this.connection = new HubConnectionBuilder() + .withAutomaticReconnect() + .withUrl(window.location.origin + '/hubs/bcfier') + .build(); + + if (this.connection.state !== HubConnectionState.Connected) { + this.ngZone.runOutsideAngular(() => { + this.connection.start(); + }); + } + + this.setUpMessageListeners(); + } + + private setUpMessageListeners(): void { + this.connection.on('InternalError', (errorMessage: string) => { + this.ngZone.run(() => { + this.notificationsService.error(errorMessage, 'CAD Error'); + this.matDialog.open(CadErrorDialogComponent, { + data: errorMessage, + }); + // We usually want to hide the loading screen if we receive an error from the CAD + // system, since that means something went wrong and waiting further is pointless + this.loadingService.hideLoadingScreen(); + }); + }); + + this.connection.on( + 'NavisworksClashIssuesTotalCount', + (totalCount: number) => { + this.ngZone.run(() => { + this.navisworksClashProgressMessengerService.navisworksClashesTotalCount.next( + totalCount + ); + }); + } + ); + + this.connection.on( + 'NavisworksClashIssuesCurrentCount', + (currentCount: number) => { + this.ngZone.run(() => { + this.navisworksClashProgressMessengerService.navisworksClashesCurrentCount.next( + currentCount + ); + }); + } + ); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/issue-filter.service.ts b/src/ipa-bcfier-ui/src/app/services/issue-filter.service.ts new file mode 100644 index 00000000..e0976237 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/issue-filter.service.ts @@ -0,0 +1,75 @@ +import { Injectable, inject } from '@angular/core'; + +import { BcfTopic } from '../generated-client/generated-client'; + +@Injectable({ + providedIn: 'root', +}) +export class IssueFilterService { + filterIssue( + issues: BcfTopic[], + withoutStatus: boolean, + status: string, + withoutType: boolean, + type: string, + withoutUser: boolean, + users: string[], + dateStart: Date | null, + dateEnd: Date | null + ): BcfTopic[] { + if (!issues || !issues.length) { + return []; + } + return issues.filter((issue) => { + let passesStatus = true; + let passesType = true; + let passesUsers = true; + let passesDate = true; + + if (withoutStatus) { + passesStatus = !issue.topicStatus; + } else if (status && issue.topicStatus !== status) { + passesStatus = false; + } + + if (withoutType) { + passesType = !issue.topicType; + } else if (type && issue.topicType !== type) { + passesType = false; + } + + if (withoutUser) { + passesUsers = !issue.assignedTo; + } else if ( + (users && + users.length > 0 && + issue.assignedTo && + !users.includes(issue.assignedTo)) || + (users.length > 0 && !issue.assignedTo) + ) { + passesUsers = false; + } + + if ( + !!issue.dueDate && + dateStart && + new Date(issue.dueDate).getTime() < new Date(dateStart).getTime() + ) { + passesDate = false; + } + + if ( + dateEnd && + !!issue.dueDate && + new Date(issue.dueDate).getTime() > new Date(dateEnd).getTime() + ) { + passesDate = false; + } + + if ((dateStart || dateEnd) && !issue.dueDate) { + passesDate = false; + } + return passesStatus && passesType && passesDate && passesUsers; + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/issue-statuses.service.ts b/src/ipa-bcfier-ui/src/app/services/issue-statuses.service.ts new file mode 100644 index 00000000..bb8ec02c --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/issue-statuses.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +export const IssueStatuses = new Set([ + 'New', + 'Active', + 'Resolved', + 'Reviewed', + 'Approved', +]); +@Injectable({ + providedIn: 'root', +}) +export class IssueStatusesService { + private issueStatusesSource = new BehaviorSubject>(IssueStatuses); + issueStatuses = this.issueStatusesSource.asObservable(); + constructor() {} + + setIssueStatuses(statuses: string | string[]): void { + const statusArray = typeof statuses === 'string' ? [statuses] : statuses; + + const updatedStatuses = new Set([...IssueStatuses, ...statusArray]); + this.issueStatusesSource.next(updatedStatuses); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/issue-types.service.ts b/src/ipa-bcfier-ui/src/app/services/issue-types.service.ts new file mode 100644 index 00000000..d306bc4a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/issue-types.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +export const IssueTypes = new Set([ + 'Architecture', + 'Structural', + 'Electrical', + 'HVAC', + 'W&S', + 'Fire Extinguishing', + 'Gas', + 'Technology', +]); +@Injectable({ + providedIn: 'root', +}) +export class IssueTypesService { + private issueTypesSource = new BehaviorSubject>(IssueTypes); + issueTypes = this.issueTypesSource.asObservable(); + constructor() {} + + setIssueTypes(types: string | string[]): void { + const statusArray = typeof types === 'string' ? [types] : types; + + const updatedTypes = new Set([...IssueTypes, ...statusArray]); + this.issueTypesSource.next(updatedTypes); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/light-query/projects.service.ts b/src/ipa-bcfier-ui/src/app/services/light-query/projects.service.ts new file mode 100644 index 00000000..62439504 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/light-query/projects.service.ts @@ -0,0 +1,48 @@ +import { CollectionViewer } from '@angular/cdk/collections'; +import { DataSource } from '@angular/cdk/table'; +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { PaginationBaseService, PaginationResult } from 'ng-lightquery'; +import { Observable, map, of } from 'rxjs'; +import { ProjectGet } from '../../generated-client/generated-client'; +import { SettingsMessengerService } from '../settings-messenger.service'; +@Injectable({ + providedIn: 'root', +}) +export class ProjectsService + extends PaginationBaseService + implements DataSource +{ + constructor( + override http: HttpClient, + private settingsMessengerService: SettingsMessengerService + ) { + super(http); + this.baseUrl = `api/projects`; + + this.settingsMessengerService.settings.subscribe((settings) => { + this.forceRefresh(); + }); + } + + disconnect(collectionViewer: CollectionViewer): void { + throw new Error('Method not implemented.'); + } + + connect(): Observable { + return this.paginationResult.pipe( + map((r: PaginationResult) => r.data) + ); + } + + onSort(event: { active: string; direction: string }): void { + if (!event.direction) { + this.sort = null; + } else { + this.sort = { + propertyName: event.active, + isDescending: event.direction === 'desc', + }; + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/light-query/users.service.ts b/src/ipa-bcfier-ui/src/app/services/light-query/users.service.ts new file mode 100644 index 00000000..3c26314b --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/light-query/users.service.ts @@ -0,0 +1,48 @@ +import { CollectionViewer } from '@angular/cdk/collections'; +import { DataSource } from '@angular/cdk/table'; +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { PaginationBaseService, PaginationResult } from 'ng-lightquery'; +import { Observable, map } from 'rxjs'; +import { UserGet } from '../../generated-client/generated-client'; +import { SettingsMessengerService } from '../settings-messenger.service'; +@Injectable({ + providedIn: 'root', +}) +export class UsersService + extends PaginationBaseService + implements DataSource +{ + constructor( + override http: HttpClient, + private settingsMessengerService: SettingsMessengerService + ) { + super(http); + this.baseUrl = `api/users`; + + this.settingsMessengerService.settings.subscribe((settings) => { + this.forceRefresh(); + }); + } + + disconnect(collectionViewer: CollectionViewer): void { + throw new Error('Method not implemented.'); + } + + connect(): Observable { + return this.paginationResult.pipe( + map((r: PaginationResult) => r.data) + ); + } + + onSort(event: { active: string; direction: string }): void { + if (!event.direction) { + this.sort = null; + } else { + this.sort = { + propertyName: event.active, + isDescending: event.direction === 'desc', + }; + } + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/loading.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/loading.service.spec.ts new file mode 100644 index 00000000..3ef07fa2 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/loading.service.spec.ts @@ -0,0 +1,15 @@ +import { LoadingService } from './loading.service'; +import { TestBed } from '@angular/core/testing'; + +describe('LoadingService', () => { + let service: LoadingService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LoadingService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/loading.service.ts b/src/ipa-bcfier-ui/src/app/services/loading.service.ts new file mode 100644 index 00000000..34189737 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/loading.service.ts @@ -0,0 +1,32 @@ +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; + +import { Injectable } from '@angular/core'; +import { LoadingScreenComponent } from '../components/loading-screen/loading-screen.component'; + +@Injectable({ + providedIn: 'root', +}) +export class LoadingService { + private matDialogRef: MatDialogRef | null = null; + + constructor(private matDialog: MatDialog) {} + + public showLoadingScreen(): void { + if (this.matDialogRef) { + return; + } + + this.matDialogRef = this.matDialog.open(LoadingScreenComponent, { + disableClose: true, + }); + } + + public hideLoadingScreen(): void { + if (!this.matDialogRef) { + return; + } + + this.matDialogRef.close(); + this.matDialogRef = null; + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.spec.ts new file mode 100644 index 00000000..4a4e072f --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { NavisworksClashProgressMessengerService } from './navisworks-clash-progress-messenger.service'; + +describe('NavisworksClashProgressMessengerService', () => { + let service: NavisworksClashProgressMessengerService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(NavisworksClashProgressMessengerService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.ts new file mode 100644 index 00000000..f25dafe5 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/messengers/navisworks-clash-progress-messenger.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class NavisworksClashProgressMessengerService { + public navisworksClashesTotalCount = new Subject(); + public navisworksClashesCurrentCount = new Subject(); + public cancelGeneration = new Subject(); +} diff --git a/src/ipa-bcfier-ui/src/app/services/navisworks-clashes-loading.service.ts b/src/ipa-bcfier-ui/src/app/services/navisworks-clashes-loading.service.ts new file mode 100644 index 00000000..e376e911 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/navisworks-clashes-loading.service.ts @@ -0,0 +1,36 @@ +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; + +import { Injectable } from '@angular/core'; +import { NavisworksClashesLoadingScreenComponent } from '../components/navisworks-clashes-loading-screen/navisworks-clashes-loading-screen.component'; + +@Injectable({ + providedIn: 'root', +}) +export class NavisworksClashesLoadingService { + private matDialogRef: MatDialogRef | null = + null; + + constructor(private matDialog: MatDialog) {} + + public showLoadingScreen(): void { + if (this.matDialogRef) { + return; + } + + this.matDialogRef = this.matDialog.open( + NavisworksClashesLoadingScreenComponent, + { + disableClose: true, + } + ); + } + + public hideLoadingScreen(): void { + if (!this.matDialogRef) { + return; + } + + this.matDialogRef.close(); + this.matDialogRef = null; + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/notifications.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/notifications.service.spec.ts new file mode 100644 index 00000000..c939c4c3 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/notifications.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { NotificationsService } from './notifications.service'; + +describe('NotificationsService', () => { + let service: NotificationsService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(NotificationsService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/notifications.service.ts b/src/ipa-bcfier-ui/src/app/services/notifications.service.ts new file mode 100644 index 00000000..d270d21a --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/notifications.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import { ToastrService } from 'ngx-toastr'; + +@Injectable({ + providedIn: 'root' +}) +export class NotificationsService { + + constructor(private toastr: ToastrService) { + } + + private readonly notificationDurationMs = 7 * 1000; // 7 seconds + + public success(message: string, title?: string): void { + this.toastr.success(message, title, { + timeOut: this.notificationDurationMs + }); + } + + public error(message: string, title?: string): void { + this.toastr.error(message, title, { + timeOut: this.notificationDurationMs + }); + } + + public info(message: string, title?: string, timeOut = 0): void { + this.toastr.info(message, title, { + timeOut: timeOut || this.notificationDurationMs + }); + } + + public warning(message: string, title?: string, timeOut = 0): void { + this.toastr.warning(message, title, { + timeOut: timeOut || this.notificationDurationMs + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/project-users.service.ts b/src/ipa-bcfier-ui/src/app/services/project-users.service.ts new file mode 100644 index 00000000..cd20cd62 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/project-users.service.ts @@ -0,0 +1,53 @@ +import { BehaviorSubject, ReplaySubject, filter, switchMap, take } from 'rxjs'; +import { + ProjectUserGet, + ProjectUsersClient, +} from '../generated-client/generated-client'; + +import { Injectable } from '@angular/core'; +import { SelectedProjectMessengerService } from './selected-project-messenger.service'; + +@Injectable({ + providedIn: 'root', +}) +export class ProjectUsersService { + private usersSource = new BehaviorSubject([]); + users = this.usersSource.asObservable(); + constructor( + private selectedProjectMessengerService: SelectedProjectMessengerService, + private projectUsersClient: ProjectUsersClient + ) { + this.getAllUsers(); + } + + setUsers(users: ProjectUserGet[]): void { + this.usersSource.next(users); + } + + refreshUsers(): void { + this.selectedProjectMessengerService.selectedProject + .pipe(take(1)) + .subscribe((project) => { + if (project) { + this.projectUsersClient + .getProjectUsersForProject(project.id) + .subscribe((users) => { + this.setUsers(users); + }); + } + }); + } + + private getAllUsers(): void { + this.selectedProjectMessengerService.selectedProject + .pipe( + filter((p) => !!p), + switchMap((p) => { + return this.projectUsersClient.getProjectUsersForProject(p?.id || ''); + }) + ) + .subscribe((users) => { + this.setUsers(users); + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/selected-project-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/selected-project-messenger.service.ts new file mode 100644 index 00000000..6f1389f9 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/selected-project-messenger.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { ProjectGet } from '../generated-client/generated-client'; + +@Injectable({ + providedIn: 'root', +}) +export class SelectedProjectMessengerService { + private selectedProjectSource = new BehaviorSubject(null); + selectedProject = this.selectedProjectSource.asObservable(); + + constructor() {} + + setSelectedProject(project: ProjectGet | null): void { + this.selectedProjectSource.next(project); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.spec.ts b/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.spec.ts new file mode 100644 index 00000000..2e4db058 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SettingsMessengerService } from './settings-messenger.service'; + +describe('SettingsMessengerService', () => { + let service: SettingsMessengerService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SettingsMessengerService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.ts new file mode 100644 index 00000000..db408af8 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/settings-messenger.service.ts @@ -0,0 +1,30 @@ +import { BackendService } from './BackendService'; +import { Injectable } from '@angular/core'; +import { ReplaySubject } from 'rxjs'; +import { Settings } from '../generated-client/generated-client'; + +@Injectable({ + providedIn: 'root', +}) +export class SettingsMessengerService { + private settingsSource = new ReplaySubject(1); + settings = this.settingsSource.asObservable(); + + constructor(private backendService: BackendService) { + backendService.getSettings().subscribe((settings) => { + this.settingsSource.next(settings); + }); + } + + saveSettings(settings: Settings): void { + this.backendService.saveSettings(settings).subscribe(() => { + this.settingsSource.next(settings); + }); + } + + refreshSettings(): void { + this.backendService.getSettings().subscribe((settings) => { + this.settingsSource.next(settings); + }); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/teams-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/teams-messenger.service.ts new file mode 100644 index 00000000..56f7c28c --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/teams-messenger.service.ts @@ -0,0 +1,163 @@ +import { + EMPTY, + Subject, + combineLatestWith, + switchMap, + take, + takeUntil, +} from 'rxjs'; +import { Injectable, OnDestroy, inject } from '@angular/core'; +import { + TeamsMessagePost, + TeamsMessagesClient, +} from '../generated-client/generated-client'; + +import { SelectedProjectMessengerService } from './selected-project-messenger.service'; +import { SettingsMessengerService } from './settings-messenger.service'; +import { TopicMessengerService } from './topic-messenger.service'; + +export enum MessageType { + AddComment = 'AddNomment', + AddViewpoint = 'AddViewpoint', + ChangeTitle = 'ChangeTitle', + AddNavisworksClashes = 'AddNavisworksClashes', +} +@Injectable({ + providedIn: 'root', +}) +export class TeamsMessengerService implements OnDestroy { + private topicMessengerService = inject(TopicMessengerService); + private settingsMessengerService = inject(SettingsMessengerService); + private selectedProjectMessengerService = inject( + SelectedProjectMessengerService + ); + private teamsMessagesClient = inject(TeamsMessagesClient); + + private destroyed$ = new Subject(); + private projectId = ''; + constructor() { + this.selectedProjectMessengerService.selectedProject + .pipe(takeUntil(this.destroyed$)) + .subscribe((p) => { + this.projectId = p?.id || ''; + }); + } + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + sendMessageToTeams(messageType: MessageType): void { + switch (messageType) { + case MessageType.AddComment: + this.sendInfoAboutAddComment(); + break; + case MessageType.AddViewpoint: + this.sendInfoAboutAddViewpoint(); + break; + case MessageType.AddNavisworksClashes: + this.sendInfoAboutAddNavisworksClashes(); + break; + case MessageType.ChangeTitle: + this.sendInfoAboutChangeTitle(); + break; + default: + return; + } + } + + private sendInfoAboutAddComment(): void { + this.topicMessengerService.selectedTopic + .pipe( + take(1), + switchMap((t) => { + const lastAddedComment = t?.comments[t?.comments.length - 1]; + if (this.projectId && lastAddedComment?.author && t?.id) { + const model: TeamsMessagePost = { + comment: lastAddedComment?.text, + username: lastAddedComment?.author, + }; + return this.teamsMessagesClient.announceNewCommentInProjectTopic( + this.projectId, + t?.id, + model + ); + } else { + return EMPTY; + } + }) + ) + .subscribe(() => {}); + } + + private sendInfoAboutAddViewpoint(): void { + this.topicMessengerService.selectedTopic + .pipe( + take(1), + combineLatestWith(this.settingsMessengerService.settings), + switchMap(([t, s]) => { + if (this.projectId && t?.id) { + const lastAddedViewpoint = t?.viewpoints[t?.viewpoints.length - 1]; + const model: TeamsMessagePost = { + viewpointBase64: lastAddedViewpoint.snapshotBase64, + username: s.username, + }; + return this.teamsMessagesClient.announceNewCommentInProjectTopic( + this.projectId, + t?.id, + model + ); + } + return EMPTY; + }) + ) + .subscribe(() => {}); + } + + private sendInfoAboutAddNavisworksClashes(): void { + this.topicMessengerService.selectedTopic + .pipe( + take(1), + combineLatestWith(this.settingsMessengerService.settings), + switchMap(([t, s]) => { + if (this.projectId && t?.id) { + const lastAddedViewpoint = t?.viewpoints[t?.viewpoints.length - 1]; + const model: TeamsMessagePost = { + comment: 'Clash Results from Navisworks added', + username: s.username, + }; + return this.teamsMessagesClient.announceNewCommentInProjectTopic( + this.projectId, + t?.id, + model + ); + } + return EMPTY; + }) + ) + .subscribe(() => {}); + } + + private sendInfoAboutChangeTitle(): void { + this.topicMessengerService.selectedTopic + .pipe( + take(1), + switchMap((t) => { + if (this.projectId && t?.id && t.creationAuthor) { + const model: TeamsMessagePost = { + topicTitle: t.title, + username: t.creationAuthor, + }; + return this.teamsMessagesClient.announceNewCommentInProjectTopic( + this.projectId, + t?.id, + model + ); + } + return EMPTY; + }) + ) + + .subscribe(() => {}); + } +} diff --git a/src/ipa-bcfier-ui/src/app/services/topic-messenger.service.ts b/src/ipa-bcfier-ui/src/app/services/topic-messenger.service.ts new file mode 100644 index 00000000..9a204222 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/services/topic-messenger.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { ReplaySubject } from 'rxjs'; +import { BcfTopic } from '../generated-client/generated-client'; + +@Injectable({ + providedIn: 'root', +}) +export class TopicMessengerService { + private selectedTopicSource = new ReplaySubject(1); + selectedTopic = this.selectedTopicSource.asObservable(); + constructor() {} + + setSelectedTopic(selectedTopic: BcfTopic | null): void { + this.selectedTopicSource.next(selectedTopic); + } +} diff --git a/src/ipa-bcfier-ui/src/app/version.ts b/src/ipa-bcfier-ui/src/app/version.ts new file mode 100644 index 00000000..da05def0 --- /dev/null +++ b/src/ipa-bcfier-ui/src/app/version.ts @@ -0,0 +1,10 @@ +// This file is automatically generated as part of the build process + +export const version = { + version: "3.0.0-initial-frontend0015", + commitInfo: "Branch.feature-initial-frontend.Sha.87cb2be7ee14547e2da12430ebf7ca9c91d95e63", + commitDate: "2024-04-02", + commitHash: "87cb2be7ee14547e2da12430ebf7ca9c91d95e63", + informationalVersion: "3.0.0-initial-frontend.15+Branch.feature-initial-frontend.Sha.87cb2be7ee14547e2da12430ebf7ca9c91d95e63", + buildDateUtc: new Date(Date.UTC(2024, 3, 2, 19, 24, 9)) +} diff --git a/src/ipa-bcfier-ui/src/assets/.gitkeep b/src/ipa-bcfier-ui/src/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-1.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-1.woff2 new file mode 100644 index 00000000..0f6e60b8 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-1.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-2.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-2.woff2 new file mode 100644 index 00000000..9d7fb7f8 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-2.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-3.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-3.woff2 new file mode 100644 index 00000000..87711c04 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-3.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-4.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-4.woff2 new file mode 100644 index 00000000..b289f002 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-4.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-5.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-5.woff2 new file mode 100644 index 00000000..c0099878 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-5.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-6.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-6.woff2 new file mode 100644 index 00000000..91231c9c Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-6.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-7.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-7.woff2 new file mode 100644 index 00000000..60681387 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-300-7.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-10.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-10.woff2 new file mode 100644 index 00000000..72ce0e98 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-10.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-11.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-11.woff2 new file mode 100644 index 00000000..fc71d944 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-11.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-12.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-12.woff2 new file mode 100644 index 00000000..6284d2e3 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-12.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-13.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-13.woff2 new file mode 100644 index 00000000..8a8de615 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-13.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-14.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-14.woff2 new file mode 100644 index 00000000..020729ef Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-14.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-8.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-8.woff2 new file mode 100644 index 00000000..22ddee9c Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-8.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-9.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-9.woff2 new file mode 100644 index 00000000..47da3629 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-400-9.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-15.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-15.woff2 new file mode 100644 index 00000000..8571683e Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-15.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-16.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-16.woff2 new file mode 100644 index 00000000..cb5834ff Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-16.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-17.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-17.woff2 new file mode 100644 index 00000000..064e94b7 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-17.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-18.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-18.woff2 new file mode 100644 index 00000000..0933dfe8 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-18.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-19.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-19.woff2 new file mode 100644 index 00000000..6b0b4afe Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-19.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-20.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-20.woff2 new file mode 100644 index 00000000..68f094cd Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-20.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-21.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-21.woff2 new file mode 100644 index 00000000..29342a8d Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/fonts/Roboto-500-21.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/fonts/fonts.css b/src/ipa-bcfier-ui/src/assets/fonts/fonts/fonts.css new file mode 100644 index 00000000..dc3b31ce --- /dev/null +++ b/src/ipa-bcfier-ui/src/assets/fonts/fonts/fonts.css @@ -0,0 +1,210 @@ +/* https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap */ +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-1.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-2.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-3.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-4.woff2') format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} + +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-5.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-6.woff2') format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url('Roboto-300-7.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-8.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-9.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-10.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-11.woff2') format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} + +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-12.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-13.woff2') format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('Roboto-400-14.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-15.woff2') format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} + +/* cyrillic */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-16.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} + +/* greek-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-17.woff2') format('woff2'); + unicode-range: U+1F00-1FFF; +} + +/* greek */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-18.woff2') format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} + +/* vietnamese */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-19.woff2') format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} + +/* latin-ext */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-20.woff2') format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url('Roboto-500-21.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/src/ipa-bcfier-ui/src/assets/fonts/icons/Material_Icons-400-1.woff2 b/src/ipa-bcfier-ui/src/assets/fonts/icons/Material_Icons-400-1.woff2 new file mode 100644 index 00000000..5492a6e7 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/fonts/icons/Material_Icons-400-1.woff2 differ diff --git a/src/ipa-bcfier-ui/src/assets/fonts/icons/fonts.css b/src/ipa-bcfier-ui/src/assets/fonts/icons/fonts.css new file mode 100644 index 00000000..a5690414 --- /dev/null +++ b/src/ipa-bcfier-ui/src/assets/fonts/icons/fonts.css @@ -0,0 +1,25 @@ +/* https://fonts.googleapis.com/icon?family=Material+Icons */ +/* fallback */ +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url('Material_Icons-400-1.woff2') format('woff2'); +} + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; +} + diff --git a/src/ipa-bcfier-ui/src/assets/images/ipa-bcfier-logo.png b/src/ipa-bcfier-ui/src/assets/images/ipa-bcfier-logo.png new file mode 100644 index 00000000..45349fb7 Binary files /dev/null and b/src/ipa-bcfier-ui/src/assets/images/ipa-bcfier-logo.png differ diff --git a/src/ipa-bcfier-ui/src/favicon.ico b/src/ipa-bcfier-ui/src/favicon.ico new file mode 100644 index 00000000..5ab6170a Binary files /dev/null and b/src/ipa-bcfier-ui/src/favicon.ico differ diff --git a/src/ipa-bcfier-ui/src/index.html b/src/ipa-bcfier-ui/src/index.html new file mode 100644 index 00000000..6cdd1275 --- /dev/null +++ b/src/ipa-bcfier-ui/src/index.html @@ -0,0 +1,34 @@ + + + + + IPA.BCFier + + + + + + + + + + + diff --git a/src/ipa-bcfier-ui/src/main.ts b/src/ipa-bcfier-ui/src/main.ts new file mode 100644 index 00000000..35b00f34 --- /dev/null +++ b/src/ipa-bcfier-ui/src/main.ts @@ -0,0 +1,6 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig) + .catch((err) => console.error(err)); diff --git a/src/ipa-bcfier-ui/src/nswag.json b/src/ipa-bcfier-ui/src/nswag.json new file mode 100644 index 00000000..1098aa1e --- /dev/null +++ b/src/ipa-bcfier-ui/src/nswag.json @@ -0,0 +1,128 @@ +{ + "runtime": "Net80", + "defaultVariables": null, + "documentGenerator": { + "aspNetCoreToOpenApi": { + "project": "../../IPA.Bcfier.App/IPA.Bcfier.App.csproj", + "msBuildProjectExtensionsPath": null, + "configuration": null, + "runtime": null, + "targetFramework": "net8.0", + "noBuild": false, + "msBuildOutputPath": null, + "verbose": true, + "workingDirectory": null, + "requireParametersWithoutDefault": false, + "apiGroupNames": null, + "defaultPropertyNameHandling": "Default", + "defaultReferenceTypeNullHandling": "Null", + "defaultDictionaryValueReferenceTypeNullHandling": "NotNull", + "defaultResponseReferenceTypeNullHandling": "NotNull", + "generateOriginalParameterNames": true, + "defaultEnumHandling": "Integer", + "flattenInheritanceHierarchy": false, + "generateKnownTypes": true, + "generateEnumMappingDescription": false, + "generateXmlObjects": false, + "generateAbstractProperties": false, + "generateAbstractSchemas": true, + "ignoreObsoleteProperties": false, + "allowReferencesWithProperties": false, + "useXmlDocumentation": true, + "resolveExternalXmlDocumentation": true, + "excludedTypeNames": [], + "serviceHost": null, + "serviceBasePath": null, + "serviceSchemes": [], + "infoTitle": "IPA.Bcfier API", + "infoDescription": null, + "infoVersion": "1.0.0", + "documentTemplate": null, + "documentProcessorTypes": [], + "operationProcessorTypes": [], + "typeNameGeneratorType": null, + "schemaNameGeneratorType": null, + "contractResolverType": null, + "serializerSettingsType": null, + "useDocumentProvider": true, + "documentName": "v1", + "aspNetCoreEnvironment": "Swagger", + "createWebHostBuilderMethod": null, + "startupType": null, + "allowNullableBodyParameters": true, + "useHttpAttributeNameAsOperationId": false, + "output": null, + "outputType": "Swagger2", + "newLineBehavior": "Auto", + "assemblyPaths": [], + "assemblyConfig": null, + "referencePaths": [], + "useNuGetCache": false + } + }, + "codeGenerators": { + "openApiToTypeScriptClient": { + "className": "{controller}Client", + "moduleName": "", + "namespace": "", + "typeScriptVersion": 4.3, + "template": "Angular", + "promiseType": "Promise", + "httpClass": "HttpClient", + "withCredentials": false, + "useSingletonProvider": true, + "injectionTokenType": "InjectionToken", + "rxJsVersion": 7, + "dateTimeType": "Date", + "nullValue": "Null", + "generateClientClasses": true, + "generateClientInterfaces": true, + "generateOptionalParameters": false, + "exportTypes": true, + "wrapDtoExceptions": false, + "exceptionClass": "SwaggerException", + "clientBaseClass": null, + "wrapResponses": false, + "wrapResponseMethods": [], + "generateResponseClasses": true, + "responseClass": "SwaggerResponse", + "protectedMethods": [], + "configurationClass": null, + "useTransformOptionsMethod": false, + "useTransformResultMethod": false, + "generateDtoTypes": true, + "operationGenerationMode": "MultipleClientsFromOperationId", + "markOptionalProperties": true, + "generateCloneMethod": false, + "typeStyle": "Interface", + "enumStyle": "Enum", + "useLeafType": false, + "classTypes": [], + "extendedClasses": [], + "extensionCode": null, + "generateDefaultValues": true, + "excludedTypeNames": [], + "excludedParameterNames": [], + "handleReferences": false, + "generateConstructorInterface": true, + "convertConstructorInterfaceData": false, + "importRequiredTypes": true, + "useGetBaseUrlMethod": false, + "baseUrlTokenName": "API_BASE_URL", + "queryNullValue": "", + "useAbortSignal": false, + "inlineNamedDictionaries": false, + "inlineNamedAny": false, + "templateDirectory": null, + "typeNameGeneratorType": null, + "propertyNameGeneratorType": null, + "enumNameGeneratorType": null, + "checksumCacheEnabled": false, + "includeHttpContext": false, + "serviceHost": null, + "serviceSchemes": null, + "output": "app/generated-client/generated-client.ts", + "newLineBehavior": "Auto" + } + } +} diff --git a/src/ipa-bcfier-ui/src/styles.scss b/src/ipa-bcfier-ui/src/styles.scss new file mode 100644 index 00000000..19f3ae08 --- /dev/null +++ b/src/ipa-bcfier-ui/src/styles.scss @@ -0,0 +1,88 @@ +// Custom Theming for Angular Material +// For more information: https://material.angular.io/guide/theming +@use '@angular/material' as mat; +// Plus imports for other components in your app. +@import "./assets/fonts/fonts/fonts.css"; +@import "./assets/fonts/icons/fonts.css"; + + +// Include the common styles for Angular Material. We include this here so that you only +// have to load a single css file for Angular Material in your app. +// Be sure that you only ever include this mixin once! +@include mat.core(); + + + +$yellow-palette: ( + 50: #fdfce5, + 100: #faf8bf, + 200: #f6f293, + 300: #f2ed66, + 400: #efe940, + 500: #eee609, + 600: #eed300, + 700: #efbb00, + 800: #efa300, + 900: #ee7800, + contrast: ( + 50: #000000, + 100: #000000, + 200: #000000, + 300: #000000, + 400: #000000, + 500: #000000, + 600: #000000, + 700: #000000, + 800: #000000, + 900: #000000, + ) +); + +// Define the palettes for your theme using the Material Design palettes available in palette.scss +// (imported above). For each palette, you can optionally specify a default, lighter, and darker +// hue. Available color palettes: https://material.io/design/color/ +$ipa-bcfier-ui-primary:mat.define-palette($yellow-palette, 500,600,700); +$ipa-bcfier-ui-accent: mat.define-palette(mat.$blue-grey-palette, A200, A100, A400); + +$ipa-bcfier-ui-primary-dark-theme:mat.define-palette(mat.$gray-palette,900); +$ipa-bcfier-ui-accent-dark-theme: mat.define-palette(mat.$blue-grey-palette, A200, A100, A400); + +// The warn palette is optional (defaults to red). +$ipa-bcfier-ui-warn: mat.define-palette(mat.$red-palette); + +// Create the theme object. A theme consists of configurations for individual +// theming systems such as "color" or "typography". +$ipa-bcfier-ui-theme: mat.define-light-theme(( + color: ( + primary: $ipa-bcfier-ui-primary, + accent: $ipa-bcfier-ui-accent, + warn: $ipa-bcfier-ui-warn, + ), + typography: mat.define-typography-config(), + density: 0 +)); + +$ipa-bcfier-ui-dark-theme: mat.define-light-theme(( + color: ( + primary: $ipa-bcfier-ui-primary-dark-theme, + accent: $ipa-bcfier-ui-accent-dark-theme, + warn: $ipa-bcfier-ui-warn, + ) +)); + +// Include theme styles for core and each component used in your app. +// Alternatively, you can import and @include the theme mixins for each component +// that you are using. +@include mat.all-component-themes($ipa-bcfier-ui-theme); + +.dark-theme { + @include mat.all-component-colors($ipa-bcfier-ui-dark-theme); +} +/* You can add global styles to this file, and also import other style files */ + +:root { + --primary-color:#{map-get($ipa-bcfier-ui-primary, 500)}; +} + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } diff --git a/src/ipa-bcfier-ui/tsconfig.app.json b/src/ipa-bcfier-ui/tsconfig.app.json new file mode 100644 index 00000000..374cc9d2 --- /dev/null +++ b/src/ipa-bcfier-ui/tsconfig.app.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/src/ipa-bcfier-ui/tsconfig.json b/src/ipa-bcfier-ui/tsconfig.json new file mode 100644 index 00000000..eb49734a --- /dev/null +++ b/src/ipa-bcfier-ui/tsconfig.json @@ -0,0 +1,32 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "esModuleInterop": true, + "sourceMap": true, + "declaration": false, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": [ + "ES2022", + "dom" + ] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/src/ipa-bcfier-ui/tsconfig.spec.json b/src/ipa-bcfier-ui/tsconfig.spec.json new file mode 100644 index 00000000..be7e9da7 --- /dev/null +++ b/src/ipa-bcfier-ui/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tests/IPA.Bcfier.Tests/IPA.Bcfier.Tests.csproj b/tests/IPA.Bcfier.Tests/IPA.Bcfier.Tests.csproj new file mode 100644 index 00000000..82d3c14a --- /dev/null +++ b/tests/IPA.Bcfier.Tests/IPA.Bcfier.Tests.csproj @@ -0,0 +1,39 @@ + + + + net8.0 + enable + enable + + false + true + Debug;Release + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/HeaderWithSingleFile.bcfzip b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/HeaderWithSingleFile.bcfzip new file mode 100644 index 00000000..747fe87f Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/HeaderWithSingleFile.bcfzip differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/MultipleTopics.bcfzip b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/MultipleTopics.bcfzip new file mode 100644 index 00000000..fbae758c Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/MultipleTopics.bcfzip differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/SingleVisibleSpace.bcfzip b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/SingleVisibleSpace.bcfzip new file mode 100644 index 00000000..e45c6948 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v2/SingleVisibleSpace.bcfzip differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/AllComponentsAndSpacesVisible.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/AllComponentsAndSpacesVisible.bcf new file mode 100644 index 00000000..b73d6f11 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/AllComponentsAndSpacesVisible.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleInvisibleWall.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleInvisibleWall.bcf new file mode 100644 index 00000000..e5367237 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleInvisibleWall.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleSpace.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleSpace.bcf new file mode 100644 index 00000000..f508f3c0 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleSpace.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleWall.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleWall.bcf new file mode 100644 index 00000000..2ef87ba4 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/SingleVisibleWall.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/UserAssignment.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/UserAssignment.bcf new file mode 100644 index 00000000..fbd5dfa8 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v21/UserAssignment.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/AllComponentsAndSpacesVisible.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/AllComponentsAndSpacesVisible.bcf new file mode 100644 index 00000000..bfdcef2d Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/AllComponentsAndSpacesVisible.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/RelatedTopicsWithBothTopicsInSameFile.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/RelatedTopicsWithBothTopicsInSameFile.bcf new file mode 100644 index 00000000..3eb93dc6 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/RelatedTopicsWithBothTopicsInSameFile.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleInvisibleWall.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleInvisibleWall.bcf new file mode 100644 index 00000000..429713bf Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleInvisibleWall.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleSpace.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleSpace.bcf new file mode 100644 index 00000000..6829d6ea Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleSpace.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleWall.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleWall.bcf new file mode 100644 index 00000000..e497b834 Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/SingleVisibleWall.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/UserAssignment.bcf b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/UserAssignment.bcf new file mode 100644 index 00000000..f9a6b33d Binary files /dev/null and b/tests/IPA.Bcfier.Tests/Resources/ImportTestCases/v3/UserAssignment.bcf differ diff --git a/tests/IPA.Bcfier.Tests/Services/BcfExportServiceTests.cs b/tests/IPA.Bcfier.Tests/Services/BcfExportServiceTests.cs new file mode 100644 index 00000000..8ac73e3c --- /dev/null +++ b/tests/IPA.Bcfier.Tests/Services/BcfExportServiceTests.cs @@ -0,0 +1,27 @@ +using IPA.Bcfier.Services; + +namespace IPA.Bcfier.Tests.Services +{ + public class BcfExportServiceTests + { + public static List TestFiles => TestFilesFactory.TestFiles; + + [Fact] + public void FindsTestFiles() + { + Assert.NotEmpty(TestFiles); + } + + [Theory] + [MemberData(nameof(TestFiles))] + public async Task CanImportThenExportBcfFile(TestFile testFile) + { + using var bcfStream = TestFilesFactory.GetTestFileStream(testFile); + var bcfImportService = new BcfImportService(); + var bcfFile = await bcfImportService.ImportBcfFileAsync(bcfStream, testFile.ToString()); + var exportedFile = new BcfExportService().ExportBcfFile(bcfFile); + Assert.NotNull(exportedFile); + Assert.True(exportedFile.Length > 0); + } + } +} diff --git a/tests/IPA.Bcfier.Tests/Services/BcfImportServiceTests.cs b/tests/IPA.Bcfier.Tests/Services/BcfImportServiceTests.cs new file mode 100644 index 00000000..46863ca6 --- /dev/null +++ b/tests/IPA.Bcfier.Tests/Services/BcfImportServiceTests.cs @@ -0,0 +1,25 @@ +using IPA.Bcfier.Services; + +namespace IPA.Bcfier.Tests.Services +{ + public class BcfImportServiceTests + { + public static List TestFiles => TestFilesFactory.TestFiles; + + [Fact] + public void FindsTestFiles() + { + Assert.NotEmpty(TestFiles); + } + + [Theory] + [MemberData(nameof(TestFiles))] + public async Task CanImportBcfFile(TestFile testFile) + { + using var bcfStream = TestFilesFactory.GetTestFileStream(testFile); + var bcfImportService = new BcfImportService(); + var bcfFile = await bcfImportService.ImportBcfFileAsync(bcfStream, testFile.ToString()); + Assert.NotNull(bcfFile); + } + } +} diff --git a/tests/IPA.Bcfier.Tests/TestFile.cs b/tests/IPA.Bcfier.Tests/TestFile.cs new file mode 100644 index 00000000..85df10d9 --- /dev/null +++ b/tests/IPA.Bcfier.Tests/TestFile.cs @@ -0,0 +1,20 @@ +namespace IPA.Bcfier.Tests +{ + public enum TestFile + { + ImportTestCases_v2_MultipleTopics, + ImportTestCases_v2_HeaderWithSingleFile, + ImportTestCases_v2_SingleVisibleSpace, + ImportTestCases_v21_AllComponentsAndSpacesVisible, + ImportTestCases_v21_SingleInvisibleWall, + ImportTestCases_v21_SingleVisibleSpace, + ImportTestCases_v21_SingleVisibleWall, + ImportTestCases_v21_UserAssignment, + ImportTestCases_v3_AllComponentsAndSpacesVisible, + ImportTestCases_v3_RelatedTopicsWithBothTopicsInSameFile, + ImportTestCases_v3_SingleInvisibleWall, + ImportTestCases_v3_SingleVisibleSpace, + ImportTestCases_v3_SingleVisibleWall, + ImportTestCases_v3_UserAssignment, + } +} \ No newline at end of file diff --git a/tests/IPA.Bcfier.Tests/TestFilesFactory.cs b/tests/IPA.Bcfier.Tests/TestFilesFactory.cs new file mode 100644 index 00000000..7ba6ef07 --- /dev/null +++ b/tests/IPA.Bcfier.Tests/TestFilesFactory.cs @@ -0,0 +1,25 @@ +namespace IPA.Bcfier.Tests +{ + public static class TestFilesFactory + { + public static List TestFiles => Enum.GetValues(typeof(TestFile)) + .Cast() + .Select(f => new object[] { f }) + .ToList(); + + public static Stream GetTestFileStream(TestFile testFile) + { + var assembly = typeof(TestFilesFactory).Assembly; + var resourceName = $"IPA.Bcfier.Tests.Resources.{testFile.ToString().Replace("_", ".")}"; + resourceName = assembly.GetManifestResourceNames() + .Single(r => r.StartsWith(resourceName)); + var resourceStream = assembly.GetManifestResourceStream(resourceName); + if (resourceStream == null) + { + throw new Exception($"Failed to find the resource stream for test file: {testFile}"); + } + + return resourceStream; + } + } +} \ No newline at end of file diff --git a/toc.yml b/toc.yml new file mode 100644 index 00000000..a36dae3a --- /dev/null +++ b/toc.yml @@ -0,0 +1,8 @@ +- name: Home + href: index.md +- name: API Documentation + href: api/ +- name: DanglDocu + href: https://docs.dangl-it.com +- name: GitHub + href: https://github.com/Dangl-IT/IPA.BCFier