├── .editorconfig ├── .gitattributes ├── .gitignore ├── DbToys.sln ├── LICENSE.md ├── PRIVACY.md ├── README.md ├── SampleTemplates ├── Acartons Admin │ ├── edit-component.tpl │ ├── edit-html.tpl │ ├── list-component.tpl │ ├── list-html.tpl │ ├── service.tpl │ └── type.tpl ├── Acartons Api │ ├── controller.tpl │ ├── dto.tpl │ ├── model.tpl │ ├── repository.tpl │ └── service.tpl └── Netcool Api │ ├── controller.tpl │ ├── dto.tpl │ └── service.tpl ├── images ├── screen1.png ├── screen2.png ├── screen3.png └── screen5.png └── src ├── .vsconfig ├── Build.props ├── DbToys.Core ├── Constants.cs ├── Database │ ├── DataBaseType.cs │ ├── Inflector.cs │ ├── MySqlSchemaReader.cs │ ├── PostgreSqlSchemaReader.cs │ ├── SchemaReader.cs │ ├── SqlServerSchemaReader.cs │ └── Table.cs ├── DbToys.Core.csproj ├── Excel │ ├── ExcelService.cs │ ├── ExcelStyleOptions.cs │ └── IExcelService.cs ├── ICodeGenerator.cs ├── Log │ └── Logger.cs ├── NameValue.cs ├── Scriban │ └── CustomScribanStringFunctions.cs └── WorkshopContext.cs └── DbToys.WinUI ├── Activation ├── ActivationHandler.cs ├── DefaultActivationHandler.cs └── IActivationHandler.cs ├── App.xaml ├── App.xaml.cs ├── Assets ├── Icons │ ├── add_file.png │ ├── add_folder.png │ ├── broken_link.png │ ├── chain_start.png │ ├── code_file.png │ ├── connected.png │ ├── database.png │ ├── database_server.png │ ├── document.png │ ├── flash_on.png │ ├── github.png │ ├── microsoft_excel.png │ ├── microsoft_sql_server.png │ ├── mysql.png │ ├── opened_folder.png │ ├── paint_palette.png │ ├── postgresql.png │ ├── refresh.png │ ├── remove.png │ ├── rename.png │ ├── sms.png │ ├── source_code.png │ └── table.png ├── LockScreenLogo.scale-200.png ├── Monaco │ ├── monaco.html │ └── vs │ │ ├── base │ │ ├── browser │ │ │ └── ui │ │ │ │ └── codicons │ │ │ │ └── codicon │ │ │ │ └── codicon.ttf │ │ ├── common │ │ │ └── worker │ │ │ │ └── simpleWorker.nls.js │ │ └── worker │ │ │ └── workerMain.js │ │ ├── basic-languages │ │ └── csharp │ │ │ └── csharp.js │ │ ├── editor │ │ ├── editor.main.css │ │ ├── editor.main.js │ │ └── editor.main.nls.js │ │ └── loader.js ├── SplashScreen.scale-400.png ├── Square150x150Logo.scale-200.png ├── Square150x150Logo.scale-400.png ├── Square310x310Logo.scale-200.png ├── Square310x310Logo.scale-400.png ├── Square44x44Logo.scale-150.png ├── Square44x44Logo.scale-200.png ├── Square44x44Logo.scale-400.png ├── Square44x44Logo.targetsize-20_altform-unplated.png ├── Square44x44Logo.targetsize-24_altform-unplated.png ├── Square44x44Logo.targetsize-256_altform-lightunplated.png ├── Square44x44Logo.targetsize-256_altform-unplated.png ├── Square44x44Logo.targetsize-32_altform-unplated.png ├── Square44x44Logo.targetsize-48_altform-lightunplated.png ├── Square44x44Logo.targetsize-48_altform-unplated.png ├── StoreLogo.scale-200.png ├── StoreLogo.scale-400.png ├── Wide310x150Logo.scale-200.png ├── WindowIcon.ico └── global.tpl ├── Behaviors ├── NavigationViewHeaderBehavior.cs └── NavigationViewHeaderMode.cs ├── CodeEditor ├── CompletionItem.cs └── CompletionItemKind.cs ├── DbToys.WinUI.csproj ├── Helpers ├── DependencyObjectHelper.cs ├── DialogFactory.cs ├── DialogHelper.cs ├── EnumToBooleanConverter.cs ├── FileSystemHelper.cs ├── FrameExtensions.cs ├── Json.cs ├── NavigationHelper.cs ├── ResourceExtensions.cs ├── RuntimeHelper.cs ├── SettingsStorageExtensions.cs ├── StorageItemIconHelper.cs ├── TitleBarHelper.cs ├── UIElementExtensions.cs └── Win32Helper.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Package.StoreAssociation.xml ├── Package.appinstaller ├── Package.appxmanifest ├── Properties └── launchsettings.json ├── README.md ├── Services ├── ActivationService.cs ├── CodeTemplateStorageService.cs ├── FileSystem │ ├── BaseStorageFile.cs │ ├── BaseStorageFolder.cs │ ├── IBaseStorageFile.cs │ └── IBaseStorageFolder.cs ├── IActivationService.cs ├── IDatabaseAccountHistory.cs ├── INavigationService.cs ├── INavigationViewService.cs ├── INotificationService.cs ├── IPageService.cs ├── IThemeSelectorService.cs ├── LoadingService.cs ├── NavigationService.cs ├── NavigationViewService.cs ├── PageService.cs ├── Settings │ ├── FileService.cs │ ├── GeneralSettingsService.cs │ ├── IFileService.cs │ ├── ISettingsService.cs │ ├── SettingsServiceBase.cs │ └── UiSettingsService.cs └── ThemeSelectorService.cs ├── Strings └── en-us │ └── Resources.resw ├── Styles ├── Colors.xaml ├── FontSizes.xaml ├── GridSplitterStyle.xaml ├── NotificationStyle.xaml ├── TextBlock.xaml └── Thickness.xaml ├── TemplateStudio.xml ├── Usings.cs ├── ViewModels ├── CodeTemplate │ ├── ActionArgs.cs │ ├── ProjectFolderItem.cs │ ├── TemplateFileItem.cs │ └── TemplateViewModel.cs ├── CodeTemplateExplorerViewModel.cs ├── Database │ ├── ConnectionItem.cs │ ├── DatabaseItem.cs │ └── TableItem.cs ├── DatabaseViewModel.cs ├── Dialogs │ ├── DynamicDialogViewModel.cs │ ├── GenerateCodeViewModel.cs │ ├── IDialog.cs │ ├── MysqlConnectViewModel.cs │ ├── PostgreSqlConnectViewModel.cs │ ├── SqlServerConnectViewModel.cs │ └── TemplateFilenameViewModel.cs ├── INavigationAware.cs ├── LogViewModel.cs ├── MainViewModel.cs ├── SettingsViewModel.cs ├── ShellViewModel.cs ├── TableDetailViewModel.cs └── TreeItem.cs ├── Views ├── CodeTemplate │ ├── TemplatePage.xaml │ └── TemplatePage.xaml.cs ├── CodeTemplateExplorerPage.xaml ├── CodeTemplateExplorerPage.xaml.cs ├── DatabasePage.xaml ├── DatabasePage.xaml.cs ├── Dialogs │ ├── DynamicDialog.xaml │ ├── DynamicDialog.xaml.cs │ ├── GenerateCodeDialog.xaml │ ├── GenerateCodeDialog.xaml.cs │ ├── MysqlConnectDialog.xaml │ ├── MysqlConnectDialog.xaml.cs │ ├── PostgreSqlConnectDialog.xaml │ ├── PostgreSqlConnectDialog.xaml.cs │ ├── SqlServerConnectDialog.xaml │ ├── SqlServerConnectDialog.xaml.cs │ ├── TemplateFilenameDialog.xaml │ └── TemplateFilenameDialog.xaml.cs ├── LogPage.xaml ├── LogPage.xaml.cs ├── MainPage.xaml ├── MainPage.xaml.cs ├── SettingsPage.xaml ├── SettingsPage.xaml.cs ├── ShellPage.xaml ├── ShellPage.xaml.cs ├── TableDetailPage.xaml └── TableDetailPage.xaml.cs ├── app.manifest └── appsettings.json /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # IDE0058: Expression value is never used 4 | dotnet_diagnostic.IDE0058.severity = silent 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> C Sharp 2 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 3 | [Bb]in/ 4 | [Oo]bj/ 5 | 6 | # mstest test results 7 | TestResults 8 | 9 | ## Ignore Visual Studio temporary files, build results, and 10 | ## files generated by popular Visual Studio add-ons. 11 | 12 | # User-specific files 13 | *.suo 14 | *.user 15 | *.sln.docstates 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Rr]elease/ 20 | x64/ 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pdb 28 | *.pgc 29 | *.pgd 30 | *.rsp 31 | *.sbr 32 | *.tlb 33 | *.tli 34 | *.tlh 35 | *.tmp 36 | *.log 37 | *.vspscc 38 | *.vssscc 39 | .builds 40 | 41 | # Visual C++ cache files 42 | ipch/ 43 | *.aps 44 | *.ncb 45 | *.opensdf 46 | *.sdf 47 | 48 | # Visual Studio profiler 49 | *.psess 50 | *.vsp 51 | *.vspx 52 | 53 | # Guidance Automation Toolkit 54 | *.gpState 55 | 56 | # ReSharper is a .NET coding add-in 57 | _ReSharper* 58 | 59 | # NCrunch 60 | *.ncrunch* 61 | .*crunch*.local.xml 62 | 63 | # Installshield output folder 64 | [Ee]xpress 65 | 66 | # DocProject is a documentation generator add-in 67 | DocProject/buildhelp/ 68 | DocProject/Help/*.HxT 69 | DocProject/Help/*.HxC 70 | DocProject/Help/*.hhc 71 | DocProject/Help/*.hhk 72 | DocProject/Help/*.hhp 73 | DocProject/Help/Html2 74 | DocProject/Help/html 75 | 76 | # Click-Once directory 77 | publish 78 | 79 | # Publish Web Output 80 | *.Publish.xml 81 | 82 | # NuGet Packages Directory 83 | packages 84 | 85 | # Windows Azure Build Output 86 | csx 87 | *.build.csdef 88 | 89 | # Windows Store app package directory 90 | AppPackages/ 91 | 92 | # Others 93 | [Bb]in 94 | [Oo]bj 95 | sql 96 | [Tt]est[Rr]esult* 97 | *.Cache 98 | ClientBin 99 | [Ss]tyle[Cc]op.* 100 | ~$* 101 | *.dbmdl 102 | Generated_Code #added for RIA/Silverlight projects 103 | 104 | # Backup & report files from converting an old project file to a newer 105 | # Visual Studio version. Backup files are not needed, because we have git ;-) 106 | _UpgradeReport_Files/ 107 | Backup*/ 108 | UpgradeLog*.XML 109 | 110 | # ReSharper is a .NET coding add-in 111 | _ReSharper*/ 112 | *.[Rr]e[Ss]harper 113 | *.DotSettings.user 114 | 115 | # JustCode is a .NET coding add-in 116 | .JustCode 117 | 118 | # TeamCity is a build add-in 119 | _TeamCity* 120 | 121 | # DotCover is a Code Coverage Tool 122 | *.dotCover 123 | 124 | # MightyMoose 125 | *.mm.* 126 | AutoTest.Net/ 127 | 128 | # Web workbench (sass) 129 | .sass-cache/ 130 | 131 | # Installshield output folder 132 | [Ee]xpress/ 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Visual Studio cache files 155 | # files ending in .cache can be ignored 156 | *.[Cc]ache 157 | # but keep track of directories ending in .cache 158 | !*.[Cc]ache/ 159 | 160 | # Others 161 | ClientBin/ 162 | *.dbproj.schemaview 163 | *.pfx 164 | *.publishsettings 165 | node_modules/ 166 | orleans.codegen.cs 167 | 168 | # RIA/Silverlight projects 169 | Generated_Code/ 170 | 171 | # SQL Server files 172 | *.mdf 173 | *.ldf 174 | 175 | # Business Intelligence projects 176 | *.rdl.data 177 | *.bim.layout 178 | *.bim_*.settings 179 | 180 | # Microsoft Fakes 181 | FakesAssemblies/ 182 | 183 | # Node.js Tools for Visual Studio 184 | .ntvs_analysis.dat 185 | 186 | # Visual Studio 6 build log 187 | *.plg 188 | 189 | # Visual Studio 6 workspace options file 190 | *.opt 191 | 192 | # Visual Studio LightSwitch build output 193 | **/*.HTMLClient/GeneratedArtifacts 194 | **/*.DesktopClient/GeneratedArtifacts 195 | **/*.DesktopClient/ModelManifest.xml 196 | **/*.Server/GeneratedArtifacts 197 | **/*.Server/ModelManifest.xml 198 | _Pvt_Extensions 199 | 200 | !/CameraSDK/* 201 | !/CameraSDK2/* 202 | .idea/ 203 | .vs/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 邱尘 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 | ### Privacy Policy 2 | 3 | Last updated: 2023-02-01 4 | 5 | This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You. 6 | We use Your anonynous Non-Personal data and health and performance data of the Service to provide and improve the Service itself. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. 7 | 8 | ### Interpretation and Definitions 9 | 10 | #### Interpretation 11 | 12 | The words of which the initial letter is capitalized have meanings defined under the following conditions. 13 | The following definitions shall have the same meaning regardless of whether they appear in singular or in plural. 14 | 15 | #### Definitions 16 | 17 | For the purposes of this Privacy Policy: 18 | 19 | + **You** means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable. 20 | + **Developer** (referred to as either "the Developer", "We", "Us" or "Our" in this Agreement) refers to DbToys's owner. 21 | + **Website** refers to DbToys's website, accessible from [github.com/neilq/DbToys](https://github.com/NeilQ/DbToys) 22 | + **Service** refers to the DbToys software. 23 | + **Service Provider** means any natural or legal person who processes the data on behalf of the Developer. It refers to third-party developer(s) or individuals contributor to facilitate the Service, to provide the Service on behalf of the Developer, to perform services related to the Service or to assist the Developer in analyzing how the Service is used. 24 | + **Personal Data** is any information that relates to an identified or identifiable individual. 25 | + **Non-Personal Data** is any information that does not relates to an identified or identifiable individual. 26 | + **Device** means any device that can access the Service such as a computer, a cellphone or a digital tablet. 27 | + **Usage Data** refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration that the Service takes to start). 28 | 29 | ### Collecting and Using Your Personal Data 30 | 31 | #### Types of Data Collected 32 | 33 | ##### Personal Data 34 | 35 | While using Our Service, We will never retain or ask You to provide Us any personally identifiable information. 36 | 37 | ##### Usage Data 38 | 39 | Usage Data is collected automatically when using the Service. 40 | Usage Data may include non-identifiable information such as error messages, performance metric, ordered list of features used during the use of the Service. 41 | Usage Data are not sent to the Developer and Service Provider. 42 | Usage Data are displayed in the "Logs" section in the Settings page of the Service. 43 | 44 | ### Links to Other Websites 45 | 46 | Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site You visit. 47 | 48 | We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services. 49 | 50 | ### Third-Party Services 51 | 52 | Our Service allow You to use a Third-Party service. We strongly advise You to review the Privacy Policy of every service You use. 53 | 54 | We have no control over and assume no responsibility for the content, privacy policies or practices of any third party services. 55 | 56 | ### Changes to this Privacy Policy 57 | 58 | We may update our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page. 59 | You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page. 60 | 61 | ### Contact Us 62 | 63 | If you have any questions about this Privacy Policy, You can contact us: 64 | 65 | + By visiting this page on Github: [github.com/neilq/DbToys](https://github.com/NeilQ/DbToys) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | logo 3 |

DbToys

4 |
5 | 6 | ## Introduction 7 | 8 | DbToys offers a set of utilities around database like view table design, exporting data dictionary, code generator. 9 | 10 | Supported databases: 11 | - Sql Server 12 | - Mysql 13 | - Postgresql 14 | 15 | ## Features 16 | ### OneClick To View Table 17 | Sometimes we just want to view the column definition and see the sample data by one click. 18 | 19 | - View table design 20 | - View Sample result data of table 21 | - Export data dictionary to excel 22 | - Code generation 23 | 24 | ### Export Database Documents 25 | - Export data dicionary to Excel 26 | - more to continue... 27 | 28 | ### Code Generation 29 | - Global templates 30 | - Customize your own code templates 31 | - Generate code files according the selected data table and the code templates 32 | 33 | ## Screenshots 34 | 35 | ![DbToys1](./images/screen1.png) 36 | 37 | ![DbToys2](./images/screen2.png) 38 | 39 | ## How to install 40 | 41 | ### Prerequisite 42 | - You need Windows 10 build 17763+ or later. 43 | - [Microsoft Edge WebView2 Runtime](https://go.microsoft.com/fwlink/p/?LinkId=2124703) should be installed. 44 | 45 | ### Via Microsoft Store 46 | [DbToys](https://apps.microsoft.com/store/detail/dbtoys/9NKCGCMR2W99) 47 | 48 | ### Via Release 49 | Go to [GitHub releases page](https://github.com/NeilQ/DbToys/releases), click on Assets at the bottom to show the files available in the release. 50 | **(No autoupdate)** 51 | 52 | ## Known issues 53 | - [Flash when using Multiple WebViews in Tab Controls](https://github.com/MicrosoftEdge/WebView2Feedback/issues/1412) 54 | - [Working with CoreWebView2 in MAUI Blazor (hybrid) in combination with Identity results in compile errors](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/3583) 55 | - [TreeView with DataTemplateSelector not reliably using selected DataTemplate](https://github.com/microsoft/microsoft-ui-xaml/issues/2121) 56 | 57 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/edit-component.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + "-edit.component.ts" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | import { 5 | Component, Output, EventEmitter, ViewChild, Input, ViewEncapsulation, OnInit 6 | } from '@angular/core'; 7 | import { NgForm } from '@angular/forms'; 8 | import { NzModalRef } from "ng-zorro-antd/modal"; 9 | import { NotificationsService, {{classname}}Service } from '@services'; 10 | import { {{classname}}, ViewAction, ModalComponentBase } from '@models'; 11 | 12 | @Component({ 13 | selector: '{{classname | string.to_kebab_case}}-edit', 14 | templateUrl: '{{classname | string.to_kebab_case}}-edit.html', 15 | encapsulation: ViewEncapsulation.None 16 | }) 17 | export class {{classname}}EditComponent extends ModalComponentBase implements OnInit { 18 | 19 | action: ViewAction; 20 | ViewAction = ViewAction; 21 | 22 | @Output() onSuccess: EventEmitter = new EventEmitter(); 23 | @Input() companyId: number; 24 | @ViewChild('editForm') editForm: NgForm; 25 | 26 | submitted: boolean = false; 27 | 28 | entity: {{classname}} = new {{classname}}(); 29 | currentId: number; 30 | 31 | constructor( 32 | private modal: NzModalRef, 33 | private apiService: {{classname}}Service, 34 | protected notifyService: NotificationsService) { 35 | super(); 36 | } 37 | 38 | changeViewAction(selectedData: any, action: ViewAction) { 39 | this.submitted = false; 40 | this.action = action; 41 | 42 | switch (this.action) { 43 | default: 44 | case ViewAction.Add: 45 | this.entity.companyId = this.companyId; 46 | break; 47 | case ViewAction.Update: 48 | this.currentId = selectedData.id; 49 | 50 | this.apiService.get(this.currentId) 51 | .then(data => { 52 | this.entity = data; 53 | }) 54 | .catch(err => { 55 | this.notifyService.error('Error', err); 56 | }); 57 | break; 58 | } 59 | } 60 | 61 | save() { 62 | if (!this.editForm.valid) { 63 | return; 64 | } 65 | this.submitted = true; 66 | 67 | switch (this.action) { 68 | default: 69 | case ViewAction.Add: 70 | this.apiService.add(this.entity) 71 | .then(() => { 72 | this.onSuccess.emit(null); 73 | this.modal.destroy(true); 74 | }) 75 | .catch((err) => { 76 | this.notifyService.error('Error', err); 77 | this.submitted = false; 78 | }); 79 | break; 80 | case ViewAction.Update: 81 | this.apiService.update(this.entity.id, this.entity) 82 | .then(() => { 83 | this.onSuccess.emit(null); 84 | this.modal.destroy(true); 85 | }) 86 | .catch((err) => { 87 | this.notifyService.error('Error', err); 88 | this.submitted = false; 89 | }); 90 | break; 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/edit-html.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + "-edit.html" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ 5 | ignoredCols=["id","add_user","add_time","update_time","update_user","marked_for_delete","delete_time","delete_user"] 6 | ~}} 7 |
8 | {{~ for col in table.columns ~}} 9 | {{~ if !(ignoredCols | array.contains col.name) && !(col.name | string.ends_with "id") ~}} 10 | 11 | {{ col.description }} 12 | 13 | {{~ if (col.db_type | get_js_property_type_of_pgsql)=="string" ~}} 14 | 15 | {{~ end ~}} 16 | {{~ if (col.db_type | get_js_property_type_of_pgsql)=="number" ~}} 17 | 18 | {{~ end ~}} 19 | 20 | 21 | 22 | {{~ end ~}} 23 | {{~ end ~}} 24 | 25 | 26 | 27 | 28 | 29 | 30 |
-------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/list-component.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + ".component.ts" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | import { Component, ViewEncapsulation } from '@angular/core'; 5 | import { CrudTableComponentBase, {{classname}}, IdNamePair } from '@models'; 6 | import { AuthService, {{classname}}Service, NotificationsService } from '@services'; 7 | import { NzModalService } from "ng-zorro-antd/modal"; 8 | import { {{classname}}EditComponent } from "./edit/{{classname | string.to_kebab_case}}-edit.component"; 9 | 10 | @Component({ 11 | selector: '{{classname | string.to_kebab_case}}', 12 | templateUrl: '{{classname | string.to_kebab_case}}.component.html', 13 | encapsulation: ViewEncapsulation.None 14 | }) 15 | export class {{classname}}Component extends CrudTableComponentBase<{{classname}}> { 16 | 17 | query = { 18 | companyId: null, 19 | }; 20 | 21 | constructor( 22 | protected apiService: {{classname}}Service, 23 | protected notifyService: NotificationsService, 24 | protected modalService: NzModalService, 25 | protected authService: AuthService) { 26 | super(authService, notifyService, apiService, modalService); 27 | } 28 | 29 | ngOnInit(): void { 30 | super.ngOnInit(); 31 | this.editTitle = ""; 32 | //this.editModalWidth = 600; 33 | //this.deleteMessage = ""; 34 | this.editComponent = {{classname}}EditComponent; 35 | this.editComponentParams = {companyId: this.companyId}; 36 | } 37 | 38 | onCompanyChanged(company: IdNamePair) { 39 | super.onCompanyChanged(company); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/list-html.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + ".component.html" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ 5 | # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction 6 | # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates 7 | # Press 'F1' to show editor commands 8 | ~}} 9 | {{~ 10 | ignoredCols=["id","add_user","add_time","update_time","update_user","marked_for_delete","delete_time","delete_user"] 11 | ~}} 12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
    20 |
  • 21 | 24 |
  • 25 |
  • 26 | 29 |
  • 30 |
  • 31 | 34 |
  • 35 |
  • 36 | 39 |
  • 40 |
41 | 42 | 45 | 46 | 47 | 49 | {{~ for col in table.columns ~}} 50 | {{~ if !(ignoredCols | array.contains col.name) && !(col.name | string.ends_with "id") ~}} 51 | {{~ if col.description && col.description!="" ~}} 52 | {{ col.description }} 53 | {{~ else ~}} 54 | {{ col.name }} 55 | {{~ end ~}} 56 | {{~ end ~}} 57 | {{~ end ~}} 58 | 59 | 60 | 61 | 62 | 64 | {{~ for col in table.columns ~}} 65 | {{~ if !(ignoredCols | array.contains col.name) && !(col.name | string.ends_with "id") ~}} 66 | {%{{{}%}data.{{col.property_name | string.to_camel_case}}{%{}}}%} 67 | {{~ end ~}} 68 | {{~ end ~}} 69 | 70 | 71 | 72 |
73 |
74 |
-------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/service.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + ".service.ts" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | import { Injectable } from '@angular/core'; 7 | import { {{ classname }} } from '@models'; 8 | import { ApiService } from '../api.service'; 9 | import { HttpClient } from '@angular/common/http'; 10 | 11 | @Injectable({ 12 | providedIn: 'root' 13 | }) 14 | export class {{classname}}Service extends ApiService<{{classname}}> { 15 | constructor(private http: HttpClient) { 16 | super('/api/{{classname | string.to_plural | string.to_snake_case}}', http); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Admin/type.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_kebab_case | string.to_singular) + ".type.ts" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | {{~ 7 | ignoredCols=["add_user","add_time","update_time","update_user","marked_for_delete","delete_time","delete_user"] 8 | ~}} 9 | 10 | export class {{classname}} { 11 | {{~ for col in table.columns ~}} 12 | {{~ if !(ignoredCols | array.contains col.name) ~}} 13 | {{ col.property_name | string.to_camel_case }}: {{ col.db_type | get_js_property_type_of_pgsql }}; 14 | {{~ end ~}} 15 | {{~ end ~}} 16 | } -------------------------------------------------------------------------------- /SampleTemplates/Acartons Api/controller.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_plural) + "Controller.cs" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Acartons.Api.Controllers.Base; 9 | using Acartons.Domain.{{ classname | string.to_plural }}; 10 | 11 | namespace Acartons.Api.Controllers; 12 | 13 | [Route("api/{{ classname | string.to_plural | string.to_snake_case }}")] 14 | [ApiExplorerSettings(GroupName = "")] 15 | [Authorize] 16 | public class {{classname | string.to_plural}}Controller : 17 | CrudControllerBase<{{classname}}, {{classname}}Dto, {{classname}}Query, {{classname}}Save> 18 | { 19 | public {{classname | string.to_plural}}Controller(I{{classname}}Service service, IControllerDependencies dependencies) 20 | : base(service, dependencies) 21 | { 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /SampleTemplates/Acartons Api/dto.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular) + "Dto.cs" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | {{~ 7 | ignoredCols=["id","add_user","add_time","update_time","update_user","marked_for_delete","delete_time","delete_user"] 8 | ~}} 9 | namespace Acartons.Domain.{{ classname | string.to_plural }}; 10 | 11 | public class {{ classname }}Save 12 | { 13 | {{~ for col in table.columns ~}} 14 | {{~ if !(ignoredCols | array.contains col.name) ~}} 15 | {{~ if col.description && col.description!="" ~}} 16 | /// 17 | /// {{col.description}} 18 | /// 19 | {{~ end ~}} 20 | public {{ col.db_type | get_property_type_of_pgsql }} {{ col.property_name | string.to_pascal_case }} { get; set; } 21 | 22 | {{~ end ~}} 23 | {{~ end ~}} 24 | } 25 | 26 | public class {{ classname }}Dto : {{ classname }}Save 27 | { 28 | public int Id { get; set; } 29 | } 30 | 31 | public class {{ classname }}Query 32 | { 33 | {{~ for col in table.columns ~}} 34 | {{~ if !(ignoredCols | array.contains col.name) && (col.name | string.ends_with "id") && col.name!="id" ~}} 35 | {{~ if col.description && col.description!="" ~}} 36 | /// 37 | /// {{col.description}} 38 | /// 39 | {{~ end ~}} 40 | public {{ col.db_type | get_property_type_of_pgsql }}? {{ col.property_name | string.to_pascal_case }} { get; set; } 41 | 42 | {{~ end ~}} 43 | {{~ end ~}} 44 | } 45 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Api/model.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular) + ".cs" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | {{~ 7 | cols= table.columns | array.map "name" 8 | ignoredCols=["id","add_user","add_time","update_time","update_user","marked_for_delete","delete_time","delete_user"] 9 | hasDeleteFields= (cols | array.contains "delete_user") && (cols | array.contains "delete_time") 10 | hasUpdateFields= (cols | array.contains "update_user") && (cols | array.contains "update_time") 11 | hasAddFields= (cols | array.contains "add_user") && (cols | array.contains "add_time") 12 | 13 | func get_base_type() 14 | if hasDeleteFields && hasAddFields && hasUpdateFields && hasAddFields 15 | ret "FullAuditedEntityBase" 16 | end 17 | if hasAddFields && hasUpdateFields 18 | ret "AuditedEntityBase" 19 | end 20 | if hasAddFields 21 | ret "CreateAuditedEntityBase" 22 | end 23 | end 24 | ~}} 25 | using System.ComponentModel.DataAnnotations.Schema; 26 | using Acartons.Core.Entities; 27 | 28 | namespace Acartons.Domain.{{ classname | string.to_plural }}; 29 | 30 | [Table("{{ table.clean_name }}")] 31 | public class {{ classname }} : {{get_base_type}} 32 | { 33 | {{~ for col in table.columns ~}} 34 | {{~ if !(ignoredCols | array.contains col.name) ~}} 35 | {{~ if col.description && col.description!="" ~}} 36 | /// 37 | /// {{col.description}} 38 | /// 39 | {{~ end ~}} 40 | public {{ col.db_type | get_property_type_of_pgsql }} {{ col.property_name | string.to_pascal_case }} { get; set; } 41 | 42 | {{~ end ~}} 43 | {{~ end ~}} 44 | } 45 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Api/repository.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular) + "Repo.cs" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | using System.Linq; 7 | using Acartons.Core.EfCore; 8 | using Acartons.Domain.EfCore; 9 | 10 | namespace Acartons.Domain.{{ classname | string.to_plural }}; 11 | 12 | public interface I{{ classname }}Repo : IEfCoreRepository<{{classname}}> 13 | { 14 | } 15 | 16 | public class {{classname}}Repo : EfCoreRepositoryBase<{{classname}}>, I{{classname}}Repo 17 | { 18 | public {{classname}}Repo(AcartonsDbContext dbContext) : base(dbContext) { } 19 | 20 | protected override IQueryable<{{classname}}> CreateFilteredQuery(object condition) 21 | { 22 | var query = base.CreateFilteredQuery(condition); 23 | if (condition is not {{classname}}Query req) return query; 24 | //query = query.Where(CreateCompanyIdFilter(req.CompanyId)); 25 | return query; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SampleTemplates/Acartons Api/service.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular) + "Service.cs" ~}} 3 | {{~ classname = table.clean_name | regex.replace "^[a-zA-Z0-9]+_" "" | string.to_pascal_case | string.to_singular ~}} 4 | {{~ # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates ~}} 5 | {{~ # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction ~}} 6 | using Acartons.Core.Services; 7 | 8 | namespace Acartons.Domain.{{ classname | string.to_plural }}; 9 | 10 | public interface I{{ classname }}Service : ICrudService<{{classname}}, {{classname}}Dto, {{classname}}Save> 11 | { 12 | } 13 | 14 | public class {{classname}}Service : UowCrudServiceBase<{{classname}}, {{classname}}Dto, {{classname}}Save>, I{{classname}}Service 15 | { 16 | public {{classname}}Service(I{{classname}}Repo repository, IUowServiceDependencies dependencies): 17 | base(repository, dependencies) 18 | { 19 | } 20 | } -------------------------------------------------------------------------------- /SampleTemplates/Netcool Api/controller.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | string.to_pascal_case | string.to_plural) + "Controller.cs" ~}} 3 | {{~ classname = table.clean_name | string.to_pascal_case | string.to_singular ~}} 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Netcool.Api.Domain.{{ classname }}; 7 | using Netcool.Core.AspNetCore.Controllers; 8 | 9 | namespace Netcool.Api.Controllers 10 | 11 | [Route("{{ table.clean_name | string.to_plural | string.to_kebab_case }}")] 12 | [Authorize] 13 | public class {{classname | string.to_plural}}Controller : 14 | CrudControllerBase<{{classname}}Dto, int, {{classname}}Request, {{classname}}SaveInput> 15 | { 16 | private new readonly I{{classname}}Service Service; 17 | 18 | public {{classname | string.to_plural}}Controller(I{{classname}}Service service) : base(service) 19 | { 20 | Service = service; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /SampleTemplates/Netcool Api/dto.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | string.to_pascal_case | string.to_singular) + "Dto.cs" ~}} 3 | {{~ classname = table.clean_name | string.to_pascal_case | string.to_singular ~}} 4 | {{~ func get_property_type_of_pgsql(db_type) 5 | case db_type 6 | when "int","int2","int8" 7 | ret "int" 8 | when "bytea" 9 | ret "byte[]" 10 | when "float4" 11 | ret "float" 12 | when "float8" 13 | ret "double" 14 | when "money","numeric" 15 | ret "decimal" 16 | when "bool","boolean" 17 | ret "bool" 18 | when "time","timetz","timestamp","timestamptz","date" 19 | ret "DateTime" 20 | else 21 | ret "string" 22 | end 23 | end ~}} 24 | {{~ func get_property_type_of_mysql(db_type) 25 | case db_type 26 | when "int","bigint","smallint" 27 | ret "int" 28 | when "image","binary","blob","mediumblob","longblob","varbinary" 29 | ret "byte[]" 30 | when "float" 31 | ret "float" 32 | when "double" 33 | ret "double" 34 | when "money","smallmoney","numeric","decimal" 35 | ret "decimal" 36 | when "bit","bool","boolean" 37 | ret "bool" 38 | when "guid" 39 | ret "Guid" 40 | when "smalldatetime","timestamp","datetime","date" 41 | ret "DateTime" 42 | else 43 | ret "string" 44 | end 45 | end ~}} 46 | {{~ func get_property_type_of_sql_server(db_type) 47 | case db_type 48 | when "int","bigint","smallint" 49 | ret "int" 50 | when "image","binary","timestamp","varbinary" 51 | ret "byte[]" 52 | when "real" 53 | ret "float" 54 | when "float","double" 55 | ret "double" 56 | when "money","smallmoney","numeric","decimal" 57 | ret "decimal" 58 | when "tinyint" 59 | ret "byte" 60 | when "bit" 61 | ret "bool" 62 | when "uniqueidentifier" 63 | ret "Guid" 64 | when "smalldatetime","datetime","datetime2","date","time" 65 | ret "DateTime" 66 | when "datetimeoffset" 67 | ret "DateTimeOffset" 68 | when "geography" 69 | ret "Microsoft.SqlServer.Types.SqlGeography" 70 | when "geometry" 71 | ret "Microsoft.SqlServer.Types.SqlGeometry" 72 | else 73 | ret "string" 74 | end 75 | end ~}} 76 | {{~ ignoredCols=["id","create_time","create_user_id","update_time","update_user_id","is_deleted","delete_time","delete_user_id"] ~}} 77 | using System; 78 | using Netcool.Core.Services.Dto; 79 | 80 | namespace Netcool.Api.Domain.{{ classname }} 81 | 82 | 83 | public class {{ classname }}SaveInput : EntityDto 84 | { 85 | {{~ for col in table.columns ~}} 86 | {{~ if col.description && col.description!="" ~}} 87 | /// 88 | /// {{col.description}} 89 | /// 90 | {{~ end ~}} 91 | {{~ if !(ignoredCols | array.contains col.name) ~}} 92 | public {{ col.db_type | get_property_type_of_pgsql }} {{ col.property_name | string.to_pascal_case }} { get; set; } 93 | 94 | {{~ end ~}} 95 | {{~ end ~}} 96 | } 97 | 98 | public class {{ classname }}Dto : {{ classname }}SaveInput 99 | { 100 | 101 | } 102 | 103 | public class {{ classname }}Query : PageRequest 104 | { 105 | 106 | } 107 | 108 | -------------------------------------------------------------------------------- /SampleTemplates/Netcool Api/service.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Required: Defines the output filename here. ~}} 2 | {{~ filename = (table.clean_name | string.to_pascal_case | string.to_singular) + "Service.cs" ~}} 3 | {{~ classname = table.clean_name | string.to_pascal_case | string.to_singular ~}} 4 | using Netcool.Core.Entities; 5 | using Netcool.Core.Repositories; 6 | using Netcool.Core.Services; 7 | 8 | namespace Netcool.Api.Domain.{{classname}} 9 | 10 | public interface I{{classname}}Service : ICrudService<{{classname}}Dto, int, {{classname}}Request> 11 | { 12 | 13 | } 14 | 15 | public class {{ classname }}Service : 16 | CrudService<{{classname}}, {{classname}}Dto, int, {{classname}}Query>, 17 | I{{classname}}Service 18 | { 19 | public {{classname}}Service(IRepository<{{classname}}> repository, IServiceAggregator serviceAggregator) : 20 | base(repository, serviceAggregator) 21 | { 22 | GetPermissionName = "{{ table.clean_name | string.to_kebab_case }}.view"; 23 | UpdatePermissionName = "{{ table.clean_name | string.to_kebab_case }}.update"; 24 | CreatePermissionName = "{{ table.clean_name | string.to_kebab_case }}.create"; 25 | DeletePermissionName = "{{ table.clean_name | string.to_kebab_case }}.delete"; 26 | } 27 | 28 | protected override IQueryable<{{classname}}> CreateFilteredQuery({{classname}}Query input) 29 | { 30 | var query = Repository.GetAll(); 31 | //query = query.Where(t => t.id == input.id); 32 | return query; 33 | } 34 | } -------------------------------------------------------------------------------- /images/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/images/screen1.png -------------------------------------------------------------------------------- /images/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/images/screen2.png -------------------------------------------------------------------------------- /images/screen3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/images/screen3.png -------------------------------------------------------------------------------- /images/screen5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/images/screen5.png -------------------------------------------------------------------------------- /src/.vsconfig: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "components": [ 4 | "Microsoft.Component.MSBuild", 5 | "Microsoft.NetCore.Component.Runtime.6.0", 6 | "Microsoft.NetCore.Component.SDK", 7 | "Microsoft.VisualStudio.Component.ManagedDesktop.Core", 8 | "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", 9 | "Microsoft.VisualStudio.Component.NuGet", 10 | "Microsoft.VisualStudio.Component.Windows10SDK.19041", 11 | "Microsoft.VisualStudio.Component.Windows10SDK", 12 | "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", 13 | "Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs", 14 | "Microsoft.VisualStudio.Workload.ManagedDesktop" 15 | ] 16 | } -------------------------------------------------------------------------------- /src/Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0.4.0 4 | 邱尘 5 | DbToys 6 | https://github.com/NeilQ/DbToys/ 7 | GitHub 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/DbToys.Core/Constants.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DbToys.Core; 3 | 4 | public static class Constants 5 | { 6 | public static class LocalSettings 7 | { 8 | public const string DatabaseHistorySettingsFileName = "database.json"; 9 | 10 | public const string GeneralSettingsFileName = "settings.json"; 11 | 12 | public const string UiSettingsFileName = "ui.json"; 13 | } 14 | 15 | public static class Notification 16 | { 17 | public const int ShortDuration = 3000; 18 | public const int DefaultDuration = 5000; 19 | } 20 | 21 | public static class FileSystem 22 | { 23 | public const string CachedEmptyItemName = "fileicon_cache"; 24 | public const string DefaultApplicationDataFolderPath = "Netcool\\DbToys"; 25 | public const string DefaultCodeTemplateFolderPath = "DbToys\\CodeTemplates"; 26 | public const string CodeTemplateFileExtension = ".tpl"; 27 | } 28 | 29 | public static class CodeTemplate 30 | { 31 | public const string InitialTemplateText = @"{{~ # Required: Defines the output filename here. ~}} 32 | {{~ filename = (table.clean_name | string.to_pascal_case | string.to_singular) + "".cs"" ~}} 33 | {{~ classname = table.clean_name | string.to_pascal_case | string.to_singular ~}} 34 | {{~ 35 | # How to write template: https://github.com/NeilQ/DbToys/wiki/Code-template-instruction 36 | # Samples link: https://github.com/NeilQ/DbToys/blob/master/SampleTemplates 37 | # Press 'F1' to show editor commands 38 | ~}} 39 | "; 40 | 41 | public const string DefaultGlobalTemplateFolderName = "$Global"; 42 | } 43 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Database/DataBaseType.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Core.Database; 2 | 3 | public enum DatabaseType 4 | { 5 | SqlServer, 6 | Mysql, 7 | PostgreSql 8 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Database/SchemaReader.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace DbToys.Core.Database; 5 | 6 | public interface ISchemaReader 7 | { 8 | string GetServerName(); 9 | 10 | string Escape(string text); 11 | 12 | List ReadDatabases(); 13 | 14 | List ReadTables(string database); 15 | 16 | List ReadColumns(string database, string schema, string table); 17 | 18 | DataTable GetResultSet(Table table, int limit, string sort); 19 | } 20 | 21 | public abstract class SchemaReader : ISchemaReader 22 | { 23 | static readonly Regex RxCleanUp = new Regex(@"[^\w\d_]", RegexOptions.Compiled); 24 | 25 | static readonly string[] CsKeywords = 26 | { 27 | "abstract", "event", "new", "struct", "as", "explicit", "null", 28 | "switch", "base", "extern", "object", "this", "bool", "false", "operator", "throw", 29 | "break", "finally", "out", "true", "byte", "fixed", "override", "try", "case", "float", 30 | "params", "typeof", "catch", "for", "private", "uint", "char", "foreach", "protected", 31 | "ulong", "checked", "goto", "public", "unchecked", "class", "if", "readonly", "unsafe", 32 | "const", "implicit", "ref", "ushort", "continue", "in", "return", "using", "decimal", 33 | "int", "sbyte", "virtual", "default", "interface", "sealed", "volatile", "delegate", 34 | "internal", "short", "void", "do", "is", "sizeof", "while", "double", "lock", 35 | "stackalloc", "else", "long", "static", "enum", "namespace", "string" 36 | }; 37 | 38 | public abstract string GetServerName(); 39 | 40 | public abstract string Escape(string text); 41 | 42 | public abstract List ReadDatabases(); 43 | 44 | public abstract List ReadColumns(string database, string schema, string table); 45 | 46 | public abstract List
ReadTables(string database); 47 | 48 | public abstract DataTable GetResultSet(Table table, int limit, string sort); 49 | 50 | /// 51 | /// Convert value to Pascal case. 52 | /// 53 | /// 54 | /// 55 | protected static string ToPascalCase(string value) 56 | { 57 | // If there are 0 or 1 characters, just return the string. 58 | if (value == null) return null; 59 | if (value.Length < 2) return value.ToUpper(); 60 | 61 | // Split the string into words. 62 | var words = value.Split( 63 | new[] { '_' }, 64 | StringSplitOptions.RemoveEmptyEntries); 65 | 66 | // Combine the words. 67 | var result = ""; 68 | foreach (var word in words) 69 | { 70 | result += 71 | word.Substring(0, 1).ToUpper() + 72 | word.Substring(1); 73 | } 74 | 75 | return result; 76 | } 77 | 78 | protected static Func CleanUp = (str) => 79 | { 80 | str = RxCleanUp.Replace(str, "_"); 81 | 82 | if (char.IsDigit(str[0]) || CsKeywords.Contains(str)) 83 | str = "@" + str; 84 | 85 | return str; 86 | }; 87 | 88 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Database/Table.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Core.Database; 2 | 3 | public class Table 4 | { 5 | public List Columns { get; set; } 6 | public string Name { get; set; } 7 | public string Schema { get; set; } 8 | public bool IsView { get; set; } 9 | public string CleanName { get; set; } 10 | public string ClassName { get; set; } 11 | public string Database { get; set; } 12 | public string Description { get; set; } 13 | 14 | public string DisplayName { get; set; } 15 | 16 | public Column Pk 17 | { 18 | get { return Columns?.FirstOrDefault(x => x.IsPk); } 19 | } 20 | 21 | public override string ToString() 22 | { 23 | return (Schema ?? "default") + "." + Name; 24 | } 25 | } 26 | 27 | public class Column 28 | { 29 | public string Name { get; set; } 30 | public string PropertyName { get; set; } 31 | public string PropertyType { get; set; } 32 | public bool IsPk { get; set; } 33 | public bool IsNullable { get; set; } 34 | public bool IsAutoIncrement { get; set; } 35 | public string DbType { get; set; } 36 | public int? Length { get; set; } 37 | public string Description { get; set; } 38 | public string DefaultValue { get; set; } 39 | } -------------------------------------------------------------------------------- /src/DbToys.Core/DbToys.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | enable 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/DbToys.Core/Excel/ExcelStyleOptions.cs: -------------------------------------------------------------------------------- 1 | using ClosedXML.Excel; 2 | 3 | namespace DbToys.Core.Excel; 4 | 5 | public class ExcelStyleOptions 6 | { 7 | public static readonly ExcelStyleOptions Default = new(); 8 | 9 | public string FontFamily { get; set; } = "Microsoft YaHei"; 10 | 11 | public double ValueFontSize { get; set; } = 11; 12 | 13 | public double TitleFontSize { get; set; } = 16; 14 | public XLAlignmentHorizontalValues TitleHorizontalAlignment { get; set; } = XLAlignmentHorizontalValues.Left; 15 | public XLColor TitleFontColor { get; set; } = XLColor.Black; 16 | public XLColor TitleBackgroundColor { get; set; } = XLColor.White; 17 | 18 | public double HeaderFontSize { get; set; } = 12; 19 | public XLColor HeaderFontColor { get; set; } = XLColor.White; 20 | public XLColor HeaderBackgroundColor { get; set; } = XLColor.FromArgb(64, 64, 64); 21 | public XLAlignmentHorizontalValues HeaderHorizontalAlignment { get; set; } = XLAlignmentHorizontalValues.Left; 22 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Excel/IExcelService.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Core.Database; 2 | 3 | namespace DbToys.Core.Excel; 4 | 5 | public interface IExcelService 6 | { 7 | public void GenerateDatabaseDictionary(IList
tableList, string fileName); 8 | } -------------------------------------------------------------------------------- /src/DbToys.Core/ICodeGenerator.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Core.Database; 2 | using DbToys.Core.Scriban; 3 | using Scriban; 4 | using Scriban.Runtime; 5 | using Scriban.Syntax; 6 | 7 | namespace DbToys.Core; 8 | 9 | public class CodeGenerateResult 10 | { 11 | public string Filename; 12 | 13 | public string Codes; 14 | 15 | public CodeGenerateResult(string filename, string codes) 16 | { 17 | Filename = filename; 18 | Codes = codes; 19 | } 20 | } 21 | 22 | public interface ICodeGenerator 23 | { 24 | public CodeGenerateResult GenerateFromTable(Table table, string templateText); 25 | 26 | } 27 | 28 | public class CodeGenerator : ICodeGenerator 29 | { 30 | public CodeGenerateResult GenerateFromTable(Table table, string templateText) 31 | { 32 | var scriptVisitor = new CodeGeneratorScriptVisitor(); 33 | var scriptObject = new ScriptObject { { "table", table } }; 34 | //scriptObject.Import(new CustomScribanStringFunctions()); 35 | var context = new TemplateContext(); 36 | context.PushGlobal(scriptObject); 37 | 38 | //context.BuiltinObject["string"] = new CustomScribanStringFunctions(); 39 | var thing = (ScriptObject)context.BuiltinObject["string"]; 40 | thing.Import(new CustomScribanStringFunctions()); 41 | 42 | var template = Template.Parse(templateText); 43 | template.Page.Accept(scriptVisitor); 44 | var output = template.Render(context); 45 | 46 | string filename = null; 47 | if (scriptVisitor.Variables.TryGetValue("filename", out var variable)) 48 | { 49 | filename = (string)variable.GetValue(context); 50 | } 51 | 52 | return new CodeGenerateResult(filename, output); 53 | } 54 | } 55 | 56 | public class CodeGeneratorScriptVisitor : ScriptVisitor 57 | { 58 | public Dictionary Variables { get; } = new(); 59 | 60 | public override void Visit(ScriptVariableGlobal node) 61 | { 62 | Variables.TryAdd(node.Name, node); 63 | base.Visit(node); 64 | } 65 | 66 | public override void Visit(ScriptVariableLocal node) 67 | { 68 | Variables.TryAdd(node.Name, node); 69 | base.Visit(node); 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Log/Logger.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Threading.Channels; 3 | using Serilog; 4 | using Serilog.Core; 5 | using Serilog.Events; 6 | using Serilog.Formatting; 7 | using Serilog.Formatting.Display; 8 | 9 | namespace DbToys.Core.Log; 10 | 11 | public static class Logger 12 | { 13 | public static readonly string ApplicationLogPath = 14 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 15 | Constants.FileSystem.DefaultApplicationDataFolderPath, "Logs"); 16 | // private static readonly LogEventSink Sink = new(); 17 | 18 | static Logger() 19 | { 20 | var logFilePath = Path.Combine(ApplicationLogPath, ".md"); 21 | Serilog.Log.Logger = new LoggerConfiguration() 22 | .MinimumLevel.Information() 23 | .WriteTo.Debug() 24 | //.WriteTo.Sink(Sink) 25 | .WriteTo.File(new MarkdownFormatter(), logFilePath, 26 | rollingInterval: RollingInterval.Day, 27 | retainedFileCountLimit:3, 28 | rollOnFileSizeLimit: true) 29 | .CreateLogger(); 30 | } 31 | 32 | public static void Information(string message) 33 | { 34 | Serilog.Log.Logger.Information(message); 35 | } 36 | 37 | public static void Error(string message) 38 | { 39 | Serilog.Log.Logger.Error(message); 40 | } 41 | 42 | public static void Error(string message, Exception e) 43 | { 44 | Serilog.Log.Logger.Error(e, message); 45 | } 46 | 47 | public static void Debug(string message) 48 | { 49 | Serilog.Log.Logger.Debug(message); 50 | } 51 | 52 | public static void Debug(string message, Exception e) 53 | { 54 | Serilog.Log.Logger.Debug(e, message); 55 | } 56 | 57 | public static void Warning(string message) 58 | { 59 | Serilog.Log.Logger.Warning(message); 60 | } 61 | } 62 | 63 | class MarkdownFormatter : ITextFormatter 64 | { 65 | public void Format(LogEvent logEvent, TextWriter output) 66 | { 67 | output.Write($"**{logEvent.Timestamp.ToLocalTime().ToString($"yyyy-MM-dd HH:mm:ss.fff zzz")}** "); 68 | if (logEvent.Level == LogEventLevel.Error || logEvent.Level == LogEventLevel.Fatal) 69 | { 70 | output.Write($"***[{logEvent.Level}]*** "); 71 | } 72 | else 73 | { 74 | output.Write($"**[{logEvent.Level}]** "); 75 | } 76 | output.WriteLine($"{logEvent.RenderMessage()} "); 77 | if (logEvent.Exception != null) 78 | { 79 | output.WriteLine($"{logEvent.Exception} "); 80 | } 81 | output.Flush(); 82 | } 83 | } 84 | 85 | class LogEventSink : ILogEventSink 86 | { 87 | readonly ITextFormatter _textFormatter; 88 | 89 | public readonly Channel Queue = Channel.CreateUnbounded(); 90 | 91 | public LogEventSink() 92 | { 93 | _textFormatter = new MessageTemplateTextFormatter(DefaultOutputTemplate); 94 | } 95 | 96 | const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"; 97 | 98 | public void Emit(LogEvent logEvent) 99 | { 100 | var message = logEvent.RenderMessage(new DateTimeFormatInfo()); 101 | var sr = new StringWriter(); 102 | _textFormatter.Format(logEvent, sr); 103 | Queue.Writer.TryWrite(sr + Environment.NewLine); 104 | } 105 | } -------------------------------------------------------------------------------- /src/DbToys.Core/NameValue.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Core; 2 | 3 | /// 4 | /// Can be used to store Name/Value (or Key/Value) pairs. 5 | /// 6 | public class NameValue : NameValue 7 | { 8 | /// 9 | /// Creates a new . 10 | /// 11 | public NameValue() 12 | { 13 | 14 | } 15 | 16 | /// 17 | /// Creates a new . 18 | /// 19 | public NameValue(string name, string value) 20 | { 21 | Name = name; 22 | Value = value; 23 | } 24 | } 25 | 26 | /// 27 | /// Can be used to store Name/Value (or Key/Value) pairs. 28 | /// 29 | public class NameValue 30 | { 31 | /// 32 | /// Name. 33 | /// 34 | public string Name { get; set; } 35 | 36 | /// 37 | /// Value. 38 | /// 39 | public T Value { get; set; } 40 | 41 | /// 42 | /// Creates a new . 43 | /// 44 | public NameValue() 45 | { 46 | 47 | } 48 | 49 | /// 50 | /// Creates a new . 51 | /// 52 | public NameValue(string name, T value) 53 | { 54 | Name = name; 55 | Value = value; 56 | } 57 | } -------------------------------------------------------------------------------- /src/DbToys.Core/Scriban/CustomScribanStringFunctions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using DbToys.Core.Database; 3 | using Scriban.Functions; 4 | 5 | namespace DbToys.Core.Scriban; 6 | 7 | public class CustomScribanStringFunctions : StringFunctions 8 | { 9 | public static string ToSingular(string text) 10 | { 11 | return Inflector.MakeSingular(text); 12 | } 13 | 14 | public static string ToPlural(string text) 15 | { 16 | return Inflector.MakePlural(text); 17 | } 18 | 19 | public static string ToCamelCase(string text) 20 | { 21 | if (string.IsNullOrWhiteSpace(text)) return string.Empty; 22 | if (text.Length < 2) return text.ToLowerInvariant(); 23 | var sb = new StringBuilder(); 24 | var chars = text.AsSpan(); 25 | 26 | sb.Append(char.ToLowerInvariant(chars[0])); 27 | var newWords = false; 28 | for (var i = 1; i < chars.Length; ++i) 29 | { 30 | var c = chars[i]; 31 | if (c is '_' or '-' or ' ') 32 | { 33 | newWords = true; 34 | continue; 35 | } 36 | 37 | if (newWords && char.IsAsciiLetter(c)) 38 | { 39 | sb.Append(char.ToUpperInvariant(c)); 40 | newWords = false; 41 | continue; 42 | } 43 | 44 | sb.Append(c); 45 | } 46 | return sb.ToString(); 47 | } 48 | 49 | public static string ToPascalCase(string text) 50 | { 51 | if (string.IsNullOrWhiteSpace(text)) return string.Empty; 52 | if (text.Length < 2) return text.ToUpperInvariant(); 53 | var sb = new StringBuilder(); 54 | var chars = text.AsSpan(); 55 | 56 | sb.Append(char.ToUpperInvariant(chars[0])); 57 | var newWords = false; 58 | for (var i = 1; i < chars.Length; ++i) 59 | { 60 | var c = chars[i]; 61 | if (c is '_' or '-' or ' ') 62 | { 63 | newWords = true; 64 | continue; 65 | } 66 | 67 | if (newWords && char.IsAsciiLetter(c)) 68 | { 69 | sb.Append(char.ToUpperInvariant(c)); 70 | newWords = false; 71 | continue; 72 | } 73 | 74 | sb.Append(c); 75 | } 76 | return sb.ToString(); 77 | } 78 | 79 | public static string ToSnakeCase(string text) 80 | { 81 | return JoinWords(text, '_'); 82 | } 83 | 84 | public static string ToKebabCase(string text) 85 | { 86 | return JoinWords(text, '-'); 87 | } 88 | 89 | public static string JoinWords(string text, char splitter) 90 | { 91 | if (string.IsNullOrWhiteSpace(text)) return string.Empty; 92 | if (text.Length < 2) return text; 93 | var sb = new StringBuilder(); 94 | var chars = text.AsSpan(); 95 | 96 | var newWords = false; 97 | sb.Append(char.ToLowerInvariant(chars[0])); 98 | for (var i = 1; i < chars.Length; ++i) 99 | { 100 | var c = chars[i]; 101 | 102 | if (c is '_' or '-' or ' ') 103 | { 104 | newWords = true; 105 | continue; 106 | } 107 | 108 | if (newWords && char.IsAsciiLetter(c)) 109 | { 110 | sb.Append(splitter); 111 | sb.Append(char.ToLowerInvariant(c)); 112 | newWords = false; 113 | continue; 114 | } 115 | 116 | if (char.IsUpper(c)) 117 | { 118 | sb.Append(splitter); 119 | sb.Append(char.ToLowerInvariant(c)); 120 | } 121 | else 122 | { 123 | sb.Append(c); 124 | } 125 | } 126 | return sb.ToString(); 127 | } 128 | } -------------------------------------------------------------------------------- /src/DbToys.Core/WorkshopContext.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DbToys.Core; 3 | 4 | public static class WorkshopContext 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Activation/ActivationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Activation; 2 | 3 | // Extend this class to implement new ActivationHandlers. See DefaultActivationHandler for an example. 4 | // https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/activation.md 5 | public abstract class ActivationHandler : IActivationHandler 6 | where T : class 7 | { 8 | // Override this method to add the logic for whether to handle the activation. 9 | protected virtual bool CanHandleInternal(T args) => true; 10 | 11 | // Override this method to add the logic for your activation handler. 12 | protected abstract Task HandleInternalAsync(T args); 13 | 14 | public bool CanHandle(object args) => args is T && CanHandleInternal((args as T)!); 15 | 16 | public async Task HandleAsync(object args) => await HandleInternalAsync((args as T)!); 17 | } 18 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Activation/DefaultActivationHandler.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Services; 2 | using DbToys.ViewModels; 3 | using Microsoft.UI.Xaml; 4 | 5 | namespace DbToys.Activation; 6 | 7 | public class DefaultActivationHandler : ActivationHandler 8 | { 9 | private readonly INavigationService _navigationService; 10 | 11 | public DefaultActivationHandler(INavigationService navigationService) 12 | { 13 | _navigationService = navigationService; 14 | } 15 | 16 | protected override bool CanHandleInternal(LaunchActivatedEventArgs args) 17 | { 18 | // None of the ActivationHandlers has handled the activation. 19 | return _navigationService.Frame?.Content == null; 20 | } 21 | 22 | protected async override Task HandleInternalAsync(LaunchActivatedEventArgs args) 23 | { 24 | _navigationService.NavigateTo(typeof(DatabaseViewModel).FullName!, args.Arguments); 25 | 26 | await Task.CompletedTask; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Activation/IActivationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Activation; 2 | 3 | public interface IActivationHandler 4 | { 5 | bool CanHandle(object args); 6 | 7 | Task HandleAsync(object args); 8 | } 9 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/add_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/add_file.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/add_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/add_folder.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/broken_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/broken_link.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/chain_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/chain_start.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/code_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/code_file.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/connected.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/database.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/database_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/database_server.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/document.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/flash_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/flash_on.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/github.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/microsoft_excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/microsoft_excel.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/microsoft_sql_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/microsoft_sql_server.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/mysql.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/opened_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/opened_folder.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/paint_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/paint_palette.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/postgresql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/postgresql.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/refresh.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/remove.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/rename.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/sms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/sms.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/source_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/source_code.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Icons/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Icons/table.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Monaco/vs/base/common/worker/simpleWorker.nls.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.34.1(0316a754aa4c25208bef91937efbce2ab1e3ce37) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/vscode/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls",{"vs/base/common/platform":["_"]}); 7 | 8 | //# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.js.map -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square310x310Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square310x310Logo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square310x310Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square310x310Logo.scale-400.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-20_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-20_altform-unplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-256_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-256_altform-lightunplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-256_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-256_altform-unplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-32_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-32_altform-unplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-48_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Square44x44Logo.targetsize-48_altform-unplated.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/WindowIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NeilQ/DbToys/59a799a6fa2dd3462f07da133ff26a8da1dadc96/src/DbToys.WinUI/Assets/WindowIcon.ico -------------------------------------------------------------------------------- /src/DbToys.WinUI/Assets/global.tpl: -------------------------------------------------------------------------------- 1 | {{~ # Global templates will be appended to all the other templates, you can define global functions or variables in the files under the global folder. ~}} 2 | 3 | {{~ func get_property_type_of_pgsql(db_type) 4 | case db_type 5 | when "int","int2","int4","int8" 6 | ret "int" 7 | when "bytea" 8 | ret "byte[]" 9 | when "float4" 10 | ret "float" 11 | when "float8" 12 | ret "double" 13 | when "money","numeric" 14 | ret "decimal" 15 | when "bool","boolean" 16 | ret "bool" 17 | when "time","timetz","timestamp","timestamptz","date" 18 | ret "DateTime" 19 | else 20 | ret "string" 21 | end 22 | end ~}} 23 | 24 | {{~ func get_property_type_of_mysql(db_type) 25 | case db_type 26 | when "int","bigint","smallint" 27 | ret "int" 28 | when "image","binary","blob","mediumblob","longblob","varbinary" 29 | ret "byte[]" 30 | when "float" 31 | ret "float" 32 | when "double" 33 | ret "double" 34 | when "money","smallmoney","numeric","decimal" 35 | ret "decimal" 36 | when "bit","bool","boolean" 37 | ret "bool" 38 | when "guid" 39 | ret "Guid" 40 | when "smalldatetime","timestamp","datetime","date" 41 | ret "DateTime" 42 | else 43 | ret "string" 44 | end 45 | end ~}} 46 | 47 | {{~ func get_property_type_of_sql_server(db_type) 48 | case db_type 49 | when "int","bigint","smallint" 50 | ret "int" 51 | when "image","binary","timestamp","varbinary" 52 | ret "byte[]" 53 | when "real" 54 | ret "float" 55 | when "float","double" 56 | ret "double" 57 | when "money","smallmoney","numeric","decimal" 58 | ret "decimal" 59 | when "tinyint" 60 | ret "byte" 61 | when "bit" 62 | ret "bool" 63 | when "uniqueidentifier" 64 | ret "Guid" 65 | when "smalldatetime","datetime","datetime2","date","time" 66 | ret "DateTime" 67 | when "datetimeoffset" 68 | ret "DateTimeOffset" 69 | when "geography" 70 | ret "Microsoft.SqlServer.Types.SqlGeography" 71 | when "geometry" 72 | ret "Microsoft.SqlServer.Types.SqlGeometry" 73 | else 74 | ret "string" 75 | end 76 | end ~}} -------------------------------------------------------------------------------- /src/DbToys.WinUI/Behaviors/NavigationViewHeaderMode.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Behaviors; 2 | 3 | public enum NavigationViewHeaderMode 4 | { 5 | Always, 6 | Never, 7 | Minimal 8 | } 9 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/CodeEditor/CompletionItemKind.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.CodeEditor; 2 | 3 | public enum CompletionItemKind 4 | { 5 | Method = 0, 6 | Function = 1, 7 | Constructor = 2, 8 | Field = 3, 9 | Variable = 4, 10 | Class = 5, 11 | Struct = 6, 12 | Interface = 7, 13 | Module = 8, 14 | Property = 9, 15 | Event = 10, 16 | Operator = 11, 17 | Unit = 12, 18 | Value = 13, 19 | Constant = 14, 20 | Enum = 15, 21 | EnumMember = 16, 22 | Keyword = 17, 23 | Text = 18, 24 | Color = 19, 25 | File = 20, 26 | Reference = 21, 27 | Customcolor = 22, 28 | Folder = 23, 29 | TypeParameter = 24, 30 | User = 25, 31 | Issue = 26, 32 | Snippet = 27 33 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/DbToys.WinUI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows10.0.19041.0 6 | 10.0.17763.0 7 | DbToys 8 | Assets/WindowIcon.ico 9 | app.manifest 10 | x64 11 | win10-x64 12 | Properties\PublishProfiles\win10-$(Platform).pubxml 13 | enable 14 | disable 15 | true 16 | true 17 | true 18 | true 19 | DbToys 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json 42 | 43 | 44 | 45 | False 46 | False 47 | True 48 | False 49 | Auto 50 | False 51 | SHA256 52 | x64 53 | 10.0.17763.0 54 | True 55 | en-US 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Always 75 | 76 | 77 | MSBuild:Compile 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | true 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/DependencyObjectHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Microsoft.UI.Xaml; 3 | using Microsoft.UI.Xaml.Media; 4 | 5 | namespace DbToys.Helpers; 6 | 7 | public static class DependencyObjectHelper 8 | { 9 | public static T FindChild(DependencyObject startNode) where T : DependencyObject 10 | { 11 | int count = VisualTreeHelper.GetChildrenCount(startNode); 12 | for (int i = 0; i < count; i++) 13 | { 14 | DependencyObject current = VisualTreeHelper.GetChild(startNode, i); 15 | if (current.GetType() == typeof(T) || current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))) 16 | { 17 | T asType = (T)current; 18 | return asType; 19 | } 20 | var retVal = FindChild(current); 21 | if (retVal is not null) 22 | { 23 | return retVal; 24 | } 25 | } 26 | return null; 27 | } 28 | 29 | public static T FindChild(DependencyObject startNode, Func predicate) where T : DependencyObject 30 | { 31 | int count = VisualTreeHelper.GetChildrenCount(startNode); 32 | for (int i = 0; i < count; i++) 33 | { 34 | DependencyObject current = VisualTreeHelper.GetChild(startNode, i); 35 | if (current.GetType() == typeof(T) || current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))) 36 | { 37 | T asType = (T)current; 38 | if (predicate(asType)) 39 | { 40 | return asType; 41 | } 42 | } 43 | var retVal = FindChild(current, predicate); 44 | if (retVal is not null) 45 | { 46 | return retVal; 47 | } 48 | } 49 | return null; 50 | } 51 | 52 | public static IEnumerable FindChildren(DependencyObject startNode) where T : DependencyObject 53 | { 54 | int count = VisualTreeHelper.GetChildrenCount(startNode); 55 | for (int i = 0; i < count; i++) 56 | { 57 | var current = VisualTreeHelper.GetChild(startNode, i); 58 | if (current.GetType() == typeof(T) || current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))) 59 | { 60 | T asType = (T)current; 61 | yield return asType; 62 | } 63 | foreach (var item in FindChildren(current)) 64 | { 65 | yield return item; 66 | } 67 | } 68 | } 69 | 70 | public static T FindParent(DependencyObject child) where T : DependencyObject 71 | { 72 | if (child is null) return null; 73 | T parent = null; 74 | 75 | var currentParent = VisualTreeHelper.GetParent(child); 76 | while (currentParent is not null) 77 | { 78 | if (currentParent is T dependencyObject) 79 | { 80 | parent = dependencyObject; 81 | break; 82 | } 83 | currentParent = VisualTreeHelper.GetParent(currentParent); 84 | } 85 | return parent; 86 | } 87 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/DialogHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace DbToys.Helpers; 4 | 5 | public class DialogHelper 6 | { 7 | public static ContentDialog SetContentDialogRoot(ContentDialog contentDialog) 8 | { 9 | contentDialog.XamlRoot = App.MainWindow.Content.XamlRoot; 10 | return contentDialog; 11 | } 12 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/EnumToBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | using Microsoft.UI.Xaml.Data; 3 | 4 | namespace DbToys.Helpers; 5 | 6 | public class EnumToBooleanConverter : IValueConverter 7 | { 8 | public EnumToBooleanConverter() 9 | { 10 | } 11 | 12 | public object Convert(object value, Type targetType, object parameter, string language) 13 | { 14 | if (parameter is string enumString) 15 | { 16 | if (!Enum.IsDefined(typeof(ElementTheme), value)) 17 | { 18 | throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum"); 19 | } 20 | 21 | var enumValue = Enum.Parse(typeof(ElementTheme), enumString); 22 | 23 | return enumValue.Equals(value); 24 | } 25 | 26 | throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName"); 27 | } 28 | 29 | public object ConvertBack(object value, Type targetType, object parameter, string language) 30 | { 31 | if (parameter is string enumString) 32 | { 33 | return Enum.Parse(typeof(ElementTheme), enumString); 34 | } 35 | 36 | throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/FileSystemHelper.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Core; 2 | 3 | namespace DbToys.Helpers; 4 | 5 | public static class FileSystemHelper 6 | { 7 | private static readonly char[] RestrictedCharacters = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }; 8 | private static readonly string[] RestrictedFileNames = { 9 | "CON", "PRN", "AUX", 10 | "NUL", "COM1", "COM2", 11 | "COM3", "COM4", "COM5", 12 | "COM6", "COM7", "COM8", 13 | "COM9", "LPT1", "LPT2", 14 | "LPT3", "LPT4", "LPT5", 15 | "LPT6", "LPT7", "LPT8", "LPT9" 16 | }; 17 | 18 | public static string GetDbToysLogFolder() 19 | { 20 | var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 21 | Constants.FileSystem.DefaultApplicationDataFolderPath, "Logs"); 22 | if (!Directory.Exists(folder)) 23 | Directory.CreateDirectory(folder); 24 | return folder; 25 | } 26 | 27 | public static string GetDbToysAppDataFolder() 28 | { 29 | var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 30 | var folder = Path.Combine(appData, Constants.FileSystem.DefaultApplicationDataFolderPath); 31 | if (!Directory.Exists(folder)) 32 | Directory.CreateDirectory(folder); 33 | return folder; 34 | } 35 | 36 | public static string FilterRestrictedCharacters(string input) 37 | { 38 | int invalidCharIndex; 39 | while ((invalidCharIndex = input.IndexOfAny(RestrictedCharacters)) >= 0) 40 | { 41 | input = input.Remove(invalidCharIndex, 1); 42 | } 43 | return input; 44 | } 45 | 46 | public static bool ContainsRestrictedCharacters(string input) 47 | { 48 | return input.IndexOfAny(RestrictedCharacters) >= 0; 49 | } 50 | 51 | public static bool ContainsRestrictedFileName(string input) 52 | { 53 | foreach (string name in RestrictedFileNames) 54 | { 55 | if (input.StartsWith(name, StringComparison.OrdinalIgnoreCase) && (input.Length == name.Length || input[name.Length] == '.')) 56 | return true; 57 | } 58 | 59 | return false; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/FrameExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace DbToys.Helpers; 4 | 5 | public static class FrameExtensions 6 | { 7 | public static object GetPageViewModel(this Frame frame) => frame?.Content?.GetType().GetProperty("ViewModel")?.GetValue(frame.Content, null); 8 | } 9 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/Json.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Text.Encodings.Web; 3 | using System.Text.Json; 4 | 5 | namespace DbToys.Helpers; 6 | 7 | public static class Json 8 | { 9 | private static JsonSerializerOptions _options = new() 10 | { 11 | Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, 12 | WriteIndented = true 13 | }; 14 | 15 | public static T Deserialize(string value) 16 | { 17 | var type = typeof(T); 18 | var typeInfo = type.GetTypeInfo(); 19 | 20 | if (typeInfo.IsPrimitive || type == typeof(string)) 21 | { 22 | return (T)Convert.ChangeType(value, type); 23 | } 24 | 25 | return JsonSerializer.Deserialize(value, _options); 26 | } 27 | 28 | public static string Serialize(object value) 29 | { 30 | var type = value.GetType(); 31 | var typeInfo = type.GetTypeInfo(); 32 | 33 | if (typeInfo.IsPrimitive || type == typeof(string)) 34 | { 35 | return (string)value; 36 | } 37 | return JsonSerializer.Serialize(value, type, _options); 38 | } 39 | 40 | public static async Task DeserializeAsync(string value) 41 | { 42 | return await Task.Run(() => Deserialize(value)); 43 | } 44 | 45 | public static async Task SerializeAsync(object value) 46 | { 47 | return await Task.Run(() => Serialize(value)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/NavigationHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | using Microsoft.UI.Xaml.Controls; 3 | 4 | namespace DbToys.Helpers; 5 | 6 | // Helper class to set the navigation target for a NavigationViewItem. 7 | // 8 | // Usage in XAML: 9 | // 10 | // 11 | // Usage in code: 12 | // NavigationHelper.SetNavigateTo(navigationViewItem, typeof(MainViewModel).FullName); 13 | public class NavigationHelper 14 | { 15 | public static string GetNavigateTo(NavigationViewItem item) => (string)item.GetValue(NavigateToProperty); 16 | 17 | public static void SetNavigateTo(NavigationViewItem item, string value) => item.SetValue(NavigateToProperty, value); 18 | 19 | public static readonly DependencyProperty NavigateToProperty = 20 | DependencyProperty.RegisterAttached("NavigateTo", typeof(string), typeof(NavigationHelper), new PropertyMetadata(null)); 21 | } 22 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/ResourceExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Windows.ApplicationModel.Resources; 2 | 3 | namespace DbToys.Helpers; 4 | 5 | public static class ResourceExtensions 6 | { 7 | private static readonly ResourceLoader _resourceLoader = new(); 8 | 9 | public static string GetLocalized(this string resourceKey) => _resourceLoader.GetString(resourceKey); 10 | } 11 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/RuntimeHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Text; 3 | 4 | namespace DbToys.Helpers; 5 | 6 | public class RuntimeHelper 7 | { 8 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 9 | private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName); 10 | 11 | public static bool IsMSIX 12 | { 13 | get 14 | { 15 | var length = 0; 16 | 17 | return GetCurrentPackageFullName(ref length, null) != 15700L; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/SettingsStorageExtensions.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | using Windows.Storage.Streams; 3 | 4 | namespace DbToys.Helpers; 5 | 6 | // Use these extension methods to store and retrieve local and roaming app data 7 | // More details regarding storing and retrieving app data at https://docs.microsoft.com/windows/apps/design/app-settings/store-and-retrieve-app-data 8 | public static class SettingsStorageExtensions 9 | { 10 | private const string FileExtension = ".json"; 11 | 12 | public static bool IsRoamingStorageAvailable(this ApplicationData appData) 13 | { 14 | return appData.RoamingStorageQuota == 0; 15 | } 16 | 17 | public static async Task SaveAsync(this StorageFolder folder, string name, T content) 18 | { 19 | var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting); 20 | var fileContent = await Json.SerializeAsync(content); 21 | 22 | await FileIO.WriteTextAsync(file, fileContent); 23 | } 24 | 25 | public static async Task ReadAsync(this StorageFolder folder, string name) 26 | { 27 | if (!File.Exists(Path.Combine(folder.Path, GetFileName(name)))) 28 | { 29 | return default; 30 | } 31 | 32 | var file = await folder.GetFileAsync($"{name}.json"); 33 | var fileContent = await FileIO.ReadTextAsync(file); 34 | 35 | return await Json.DeserializeAsync(fileContent); 36 | } 37 | 38 | public static async Task SaveAsync(this ApplicationDataContainer settings, string key, T value) 39 | { 40 | settings.SaveString(key, await Json.SerializeAsync(value)); 41 | } 42 | 43 | public static void SaveString(this ApplicationDataContainer settings, string key, string value) 44 | { 45 | settings.Values[key] = value; 46 | } 47 | 48 | public static async Task ReadAsync(this ApplicationDataContainer settings, string key) 49 | { 50 | object obj; 51 | 52 | if (settings.Values.TryGetValue(key, out obj)) 53 | { 54 | return await Json.DeserializeAsync((string)obj); 55 | } 56 | 57 | return default; 58 | } 59 | 60 | public static async Task SaveFileAsync(this StorageFolder folder, byte[] content, string fileName, CreationCollisionOption options = CreationCollisionOption.ReplaceExisting) 61 | { 62 | if (content == null) 63 | { 64 | throw new ArgumentNullException(nameof(content)); 65 | } 66 | 67 | if (string.IsNullOrEmpty(fileName)) 68 | { 69 | throw new ArgumentException("File name is null or empty. Specify a valid file name", nameof(fileName)); 70 | } 71 | 72 | var storageFile = await folder.CreateFileAsync(fileName, options); 73 | await FileIO.WriteBytesAsync(storageFile, content); 74 | return storageFile; 75 | } 76 | 77 | public static async Task ReadFileAsync(this StorageFolder folder, string fileName) 78 | { 79 | var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false); 80 | 81 | if ((item != null) && item.IsOfType(StorageItemTypes.File)) 82 | { 83 | var storageFile = await folder.GetFileAsync(fileName); 84 | var content = await storageFile.ReadBytesAsync(); 85 | return content; 86 | } 87 | 88 | return null; 89 | } 90 | 91 | public static async Task ReadBytesAsync(this StorageFile file) 92 | { 93 | if (file != null) 94 | { 95 | using IRandomAccessStream stream = await file.OpenReadAsync(); 96 | using var reader = new DataReader(stream.GetInputStreamAt(0)); 97 | await reader.LoadAsync((uint)stream.Size); 98 | var bytes = new byte[stream.Size]; 99 | reader.ReadBytes(bytes); 100 | return bytes; 101 | } 102 | 103 | return null; 104 | } 105 | 106 | private static string GetFileName(string name) 107 | { 108 | return string.Concat(name, FileExtension); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/StorageItemIconHelper.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | using Windows.Storage.FileProperties; 3 | using DbToys.Core; 4 | 5 | namespace DbToys.Helpers; 6 | 7 | public class StorageItemIconHelper 8 | { 9 | public static async Task GetIconForItemType(uint requestedSize, string fileExtension = null) 10 | { 11 | if (string.IsNullOrEmpty(fileExtension)) 12 | { 13 | var localFolder = ApplicationData.Current.RoamingFolder; 14 | return await localFolder.GetThumbnailAsync(ThumbnailMode.ListView, requestedSize, ThumbnailOptions.UseCurrentScale); 15 | } 16 | 17 | var emptyFile = await ApplicationData.Current.LocalCacheFolder.CreateFileAsync(string.Concat(Constants.FileSystem.CachedEmptyItemName, fileExtension), CreationCollisionOption.OpenIfExists); 18 | var icon = await emptyFile.GetThumbnailAsync(ThumbnailMode.ListView, requestedSize, ThumbnailOptions.UseCurrentScale); 19 | 20 | return icon; 21 | } 22 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/TitleBarHelper.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI; 2 | using Microsoft.UI; 3 | using Microsoft.UI.Xaml; 4 | using Microsoft.UI.Xaml.Media; 5 | 6 | namespace DbToys.Helpers; 7 | 8 | // Helper class to workaround custom title bar bugs. 9 | // DISCLAIMER: The resource key names and color values used below are subject to change. Do not depend on them. 10 | // https://github.com/microsoft/TemplateStudio/issues/4516 11 | internal class TitleBarHelper 12 | { 13 | private const int WAINACTIVE = 0x00; 14 | private const int WAACTIVE = 0x01; 15 | private const int WMACTIVATE = 0x0006; 16 | 17 | public static void UpdateTitleBar(ElementTheme theme) 18 | { 19 | if (App.MainWindow.ExtendsContentIntoTitleBar) 20 | { 21 | if (theme != ElementTheme.Default) 22 | { 23 | Application.Current.Resources["WindowCaptionForeground"] = theme switch 24 | { 25 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 26 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 27 | _ => new SolidColorBrush(Colors.Transparent) 28 | }; 29 | 30 | Application.Current.Resources["WindowCaptionForegroundDisabled"] = theme switch 31 | { 32 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF)), 33 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x66, 0x00, 0x00, 0x00)), 34 | _ => new SolidColorBrush(Colors.Transparent) 35 | }; 36 | 37 | Application.Current.Resources["WindowCaptionButtonBackgroundPointerOver"] = theme switch 38 | { 39 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x33, 0xFF, 0xFF, 0xFF)), 40 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x33, 0x00, 0x00, 0x00)), 41 | _ => new SolidColorBrush(Colors.Transparent) 42 | }; 43 | 44 | Application.Current.Resources["WindowCaptionButtonBackgroundPressed"] = theme switch 45 | { 46 | ElementTheme.Dark => new SolidColorBrush(Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF)), 47 | ElementTheme.Light => new SolidColorBrush(Color.FromArgb(0x66, 0x00, 0x00, 0x00)), 48 | _ => new SolidColorBrush(Colors.Transparent) 49 | }; 50 | 51 | Application.Current.Resources["WindowCaptionButtonStrokePointerOver"] = theme switch 52 | { 53 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 54 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 55 | _ => new SolidColorBrush(Colors.Transparent) 56 | }; 57 | 58 | Application.Current.Resources["WindowCaptionButtonStrokePressed"] = theme switch 59 | { 60 | ElementTheme.Dark => new SolidColorBrush(Colors.White), 61 | ElementTheme.Light => new SolidColorBrush(Colors.Black), 62 | _ => new SolidColorBrush(Colors.Transparent) 63 | }; 64 | } 65 | 66 | Application.Current.Resources["WindowCaptionBackground"] = new SolidColorBrush(Colors.Transparent); 67 | Application.Current.Resources["WindowCaptionBackgroundDisabled"] = new SolidColorBrush(Colors.Transparent); 68 | 69 | var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow); 70 | if (hwnd == Win32Helper.GetActiveWindow()) 71 | { 72 | Win32Helper.SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero); 73 | Win32Helper.SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero); 74 | } 75 | else 76 | { 77 | Win32Helper.SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero); 78 | Win32Helper.SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/UIElementExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Microsoft.UI.Input; 3 | using Microsoft.UI.Xaml; 4 | 5 | namespace DbToys.Helpers; 6 | 7 | public static class UIElementExtensions 8 | { 9 | public static void ChangeCursor(this UIElement uiElement, InputCursor cursor) 10 | { 11 | Type type = typeof(UIElement); 12 | type.InvokeMember("ProtectedCursor", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, uiElement, new object[] { cursor }); 13 | } 14 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Helpers/Win32Helper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace DbToys.Helpers; 4 | 5 | public static class Win32Helper 6 | { 7 | [DllImport("user32.dll")] 8 | public static extern IntPtr GetActiveWindow(); 9 | 10 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 11 | public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam); 12 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Helpers; 2 | 3 | namespace DbToys; 4 | 5 | public sealed partial class MainWindow : WindowEx 6 | { 7 | public MainWindow() 8 | { 9 | InitializeComponent(); 10 | 11 | AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico")); 12 | Content = null; 13 | Title = "AppDisplayName".GetLocalized(); 14 | this.CenterOnScreen(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Package.appinstaller: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 11 | 12 | 16 | 17 | 18 | DbToys 19 | 邱尘 20 | Assets\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Properties/launchsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "WSL": { 4 | "commandName": "WSL2", 5 | "distributionName": "" 6 | }, 7 | "Netcool.DbToys.WinUI (Unpackaged)": { 8 | "commandName": "Project" 9 | }, 10 | "Netcool.DbToys.WinUI (Package)": { 11 | "commandName": "MsixPackage" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/README.md: -------------------------------------------------------------------------------- 1 | *Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)* 2 | 3 | ## Getting Started 4 | 5 | Browse and address `TODO:` comments in `View -> Task List` to learn the codebase and understand next steps for turning the generated code into production code. 6 | 7 | Explore the [WinUI Gallery](https://www.microsoft.com/store/productId/9P3JFPWWDZRC) to learn about available controls and design patterns. 8 | 9 | Relaunch Template Studio to modify the project by right-clicking on the project in `View -> Solution Explorer` then selecting `Add -> New Item (Template Studio)`. 10 | 11 | ## Publishing 12 | 13 | For projects with MSIX packaging, right-click on the application project and select `Package and Publish -> Create App Packages...` to create an MSIX package. 14 | 15 | For projects without MSIX packaging, follow the [deployment guide](https://docs.microsoft.com/windows/apps/windows-app-sdk/deploy-unpackaged-apps) or add the `Self-Contained` Feature to enable xcopy deployment. 16 | 17 | ## CI Pipelines 18 | 19 | See [README.md](https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/pipelines/README.md) for guidance on building and testing projects in CI pipelines. 20 | 21 | ## Changelog 22 | 23 | See [releases](https://github.com/microsoft/TemplateStudio/releases) and [milestones](https://github.com/microsoft/TemplateStudio/milestones). 24 | 25 | ## Feedback 26 | 27 | Bugs and feature requests should be filed at https://aka.ms/templatestudio. 28 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/ActivationService.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Activation; 2 | using DbToys.Views; 3 | using Microsoft.UI.Xaml; 4 | using Microsoft.UI.Xaml.Controls; 5 | 6 | namespace DbToys.Services; 7 | 8 | public class ActivationService : IActivationService 9 | { 10 | private readonly ActivationHandler _defaultHandler; 11 | private readonly IEnumerable _activationHandlers; 12 | private readonly IThemeSelectorService _themeSelectorService; 13 | private UIElement _shell = null; 14 | 15 | public ActivationService(ActivationHandler defaultHandler, IEnumerable activationHandlers, IThemeSelectorService themeSelectorService) 16 | { 17 | _defaultHandler = defaultHandler; 18 | _activationHandlers = activationHandlers; 19 | _themeSelectorService = themeSelectorService; 20 | } 21 | 22 | public async Task ActivateAsync(object activationArgs) 23 | { 24 | // Execute tasks before activation. 25 | await InitializeAsync(); 26 | 27 | // Set the MainWindow Content. 28 | if (App.MainWindow.Content == null) 29 | { 30 | _shell = App.GetService(); 31 | App.MainWindow.Content = _shell ?? new Frame(); 32 | } 33 | 34 | // Handle activation via ActivationHandlers. 35 | await HandleActivationAsync(activationArgs); 36 | 37 | // Activate the MainWindow. 38 | App.MainWindow.Activate(); 39 | 40 | // Execute tasks after activation. 41 | await StartupAsync(); 42 | } 43 | 44 | private async Task HandleActivationAsync(object activationArgs) 45 | { 46 | var activationHandler = _activationHandlers.FirstOrDefault(h => h.CanHandle(activationArgs)); 47 | 48 | if (activationHandler != null) 49 | { 50 | await activationHandler.HandleAsync(activationArgs); 51 | } 52 | 53 | if (_defaultHandler.CanHandle(activationArgs)) 54 | { 55 | await _defaultHandler.HandleAsync(activationArgs); 56 | } 57 | } 58 | 59 | private async Task InitializeAsync() 60 | { 61 | await _themeSelectorService.InitializeAsync().ConfigureAwait(false); 62 | await Task.CompletedTask; 63 | } 64 | 65 | private async Task StartupAsync() 66 | { 67 | await _themeSelectorService.SetRequestedThemeAsync(); 68 | await Task.CompletedTask; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/CodeTemplateStorageService.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Windows.Storage; 3 | using Windows.Storage.Search; 4 | using DbToys.Core; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace DbToys.Services; 8 | 9 | public class CodeTemplateStorageService 10 | { 11 | public string TemplateFolderPath { get; } = Path.Combine( 12 | Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), 13 | Constants.FileSystem.DefaultCodeTemplateFolderPath); 14 | 15 | public StorageFolder TemplateFolder { get; private set; } 16 | 17 | public async Task> GetProjectFoldersAsync() 18 | { 19 | await EnsureTemplateFolder(); 20 | await EnsureGlobalProject(); 21 | var folders = await TemplateFolder.GetFoldersAsync(); 22 | return folders.ToList(); 23 | } 24 | 25 | public async Task> GetTemplateFilesAsync(StorageFolder folder) 26 | { 27 | ArgumentNullException.ThrowIfNull(nameof(folder)); 28 | var files = (await folder.GetFilesAsync(CommonFileQuery.OrderByName)).ToList(); 29 | if (folder.Name == Constants.CodeTemplate.DefaultGlobalTemplateFolderName && files.Count == 0) 30 | { 31 | var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/global.tpl")); 32 | var defaultGlobalTemplate = await file.CopyAsync(folder, file.Name); 33 | 34 | files.Add(defaultGlobalTemplate); 35 | } 36 | return files; 37 | } 38 | 39 | public async Task CreateProjectFolder(string folderName) 40 | { 41 | if (string.IsNullOrEmpty(folderName)) return null; 42 | await EnsureTemplateFolder(); 43 | if (Directory.Exists(Path.Join(TemplateFolderPath, folderName))) return null; 44 | var folder = await TemplateFolder.CreateFolderAsync(folderName); 45 | return folder; 46 | } 47 | 48 | public async Task CreateTemplateFile(StorageFolder folder, string filename, string initText) 49 | { 50 | if (folder == null || string.IsNullOrEmpty(filename)) return null; 51 | 52 | var file = await folder.CreateFileAsync(filename, CreationCollisionOption.FailIfExists); 53 | if (!string.IsNullOrEmpty(initText)) 54 | { 55 | await FileIO.WriteTextAsync(file, Constants.CodeTemplate.InitialTemplateText); 56 | } 57 | 58 | return file; 59 | } 60 | 61 | public async Task GetGlobalTemplateText() 62 | { 63 | var folder = await TemplateFolder.GetFolderAsync(Constants.CodeTemplate.DefaultGlobalTemplateFolderName); 64 | var files = await folder.GetFilesAsync(); 65 | if (files == null || files.Count == 0) return null; 66 | var sb = new StringBuilder(); 67 | foreach (var file in files) 68 | { 69 | var text = await FileIO.ReadTextAsync(file); 70 | if (string.IsNullOrWhiteSpace(text)) continue; 71 | sb.AppendLine(Regex.Replace(text, @"^\s*$\n|\r", string.Empty, RegexOptions.Multiline).Trim()); 72 | } 73 | 74 | return sb.ToString(); 75 | } 76 | 77 | 78 | private async Task EnsureTemplateFolder() 79 | { 80 | if (TemplateFolder != null) return; 81 | 82 | if (!Directory.Exists(TemplateFolderPath)) 83 | { 84 | Directory.CreateDirectory(TemplateFolderPath); 85 | } 86 | 87 | TemplateFolder = await StorageFolder.GetFolderFromPathAsync(TemplateFolderPath); 88 | } 89 | 90 | private async Task EnsureGlobalProject() 91 | { 92 | var item = await TemplateFolder.TryGetItemAsync(Constants.CodeTemplate.DefaultGlobalTemplateFolderName); 93 | if (item is StorageFolder) 94 | { 95 | return; 96 | } 97 | 98 | await TemplateFolder.CreateFolderAsync(Constants.CodeTemplate.DefaultGlobalTemplateFolderName); 99 | } 100 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/FileSystem/BaseStorageFolder.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services.FileSystem; 2 | 3 | public abstract class BaseStorageFolder 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/FileSystem/IBaseStorageFile.cs: -------------------------------------------------------------------------------- 1 | using Windows.Foundation; 2 | using Windows.Storage; 3 | using Windows.Storage.FileProperties; 4 | 5 | namespace DbToys.Services.FileSystem; 6 | 7 | public interface IBaseStorageFile : IStorageItem2, IStorageFile, IStorageFile2 8 | , IStorageItemProperties2, IStorageItemPropertiesWithProvider, IStorageFilePropertiesWithAvailability 9 | { 10 | new IStorageItemExtraProperties Properties { get; } 11 | 12 | IAsyncOperation ToStorageFileAsync(); 13 | 14 | new IAsyncOperation GetParentAsync(); 15 | //new IAsyncOperation GetBasicPropertiesAsync(); 16 | 17 | new IAsyncOperation CopyAsync(IStorageFolder destinationFolder); 18 | new IAsyncOperation CopyAsync(IStorageFolder destinationFolder, string desiredNewName); 19 | new IAsyncOperation CopyAsync(IStorageFolder destinationFolder, string desiredNewName, NameCollisionOption option); 20 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/FileSystem/IBaseStorageFolder.cs: -------------------------------------------------------------------------------- 1 | using Windows.Foundation; 2 | using Windows.Storage; 3 | using Windows.Storage.FileProperties; 4 | using Windows.Storage.Search; 5 | 6 | namespace DbToys.Services.FileSystem; 7 | 8 | public interface IBaseStorageFolder : IStorageItem2, IStorageFolder, IStorageFolder2 9 | , IStorageItemProperties2, IStorageItemPropertiesWithProvider, IStorageFolderQueryOperations 10 | { 11 | new IStorageItemExtraProperties Properties { get; } 12 | 13 | IAsyncOperation ToStorageFolderAsync(); 14 | 15 | new IAsyncOperation GetParentAsync(); 16 | //new IAsyncOperation GetBasicPropertiesAsync(); 17 | 18 | new IAsyncOperation GetItemAsync(string name); 19 | new IAsyncOperation> GetItemsAsync(); 20 | 21 | new IAsyncOperation GetFileAsync(string name); 22 | new IAsyncOperation> GetFilesAsync(); 23 | new IAsyncOperation> GetFilesAsync(CommonFileQuery query); 24 | new IAsyncOperation> GetFilesAsync(CommonFileQuery query, uint startIndex, uint maxItemsToRetrieve); 25 | 26 | new IAsyncOperation GetFolderAsync(string name); 27 | new IAsyncOperation> GetFoldersAsync(); 28 | new IAsyncOperation> GetFoldersAsync(CommonFolderQuery query); 29 | new IAsyncOperation> GetFoldersAsync(CommonFolderQuery query, uint startIndex, uint maxItemsToRetrieve); 30 | 31 | new IAsyncOperation CreateFileAsync(string desiredName); 32 | new IAsyncOperation CreateFileAsync(string desiredName, CreationCollisionOption options); 33 | new IAsyncOperation CreateFolderAsync(string desiredName); 34 | new IAsyncOperation CreateFolderAsync(string desiredName, CreationCollisionOption options); 35 | 36 | //new BaseStorageItemQueryResult CreateItemQueryWithOptions(QueryOptions queryOptions); 37 | //new BaseStorageFileQueryResult CreateFileQueryWithOptions(QueryOptions queryOptions); 38 | //new BaseStorageFolderQueryResult CreateFolderQueryWithOptions(QueryOptions queryOptions); 39 | } 40 | 41 | public interface ICreateFileWithStream 42 | { 43 | IAsyncOperation CreateFileAsync(Stream contents, string desiredName); 44 | 45 | IAsyncOperation CreateFileAsync(Stream contents, string desiredName, CreationCollisionOption options); 46 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/IActivationService.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services; 2 | 3 | public interface IActivationService 4 | { 5 | Task ActivateAsync(object activationArgs); 6 | } 7 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/INavigationService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | using Microsoft.UI.Xaml.Navigation; 3 | 4 | namespace DbToys.Services; 5 | 6 | public interface INavigationService 7 | { 8 | event NavigatedEventHandler Navigated; 9 | 10 | bool CanGoBack 11 | { 12 | get; 13 | } 14 | 15 | Frame Frame 16 | { 17 | get; set; 18 | } 19 | 20 | bool NavigateTo(string pageKey, object parameter = null, bool clearNavigation = false); 21 | 22 | bool GoBack(); 23 | } 24 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/INavigationViewService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | 3 | namespace DbToys.Services; 4 | 5 | public interface INavigationViewService 6 | { 7 | IList MenuItems 8 | { 9 | get; 10 | } 11 | 12 | object SettingsItem 13 | { 14 | get; 15 | } 16 | 17 | void Initialize(NavigationView navigationView); 18 | 19 | void UnregisterEvents(); 20 | 21 | NavigationViewItem GetSelectedItem(Type pageType); 22 | } 23 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/IPageService.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services; 2 | 3 | public interface IPageService 4 | { 5 | Type GetPageType(string key); 6 | } 7 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/IThemeSelectorService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | namespace DbToys.Services; 4 | 5 | public interface IThemeSelectorService 6 | { 7 | ElementTheme Theme 8 | { 9 | get; 10 | } 11 | 12 | Task InitializeAsync(); 13 | 14 | Task SetThemeAsync(ElementTheme theme); 15 | 16 | Task SetRequestedThemeAsync(); 17 | } 18 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/LoadingService.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services; 2 | 3 | public interface ILoadingService 4 | { 5 | public void Active(string text = null); 6 | public void Dismiss(); 7 | public Action LoadingRequested { get; set; } 8 | } 9 | 10 | public class LoadingService : ILoadingService 11 | { 12 | public void Active(string text = null) 13 | { 14 | LoadingRequested(true, text); 15 | } 16 | 17 | public void Dismiss() 18 | { 19 | LoadingRequested(false, null); 20 | } 21 | 22 | public Action LoadingRequested { get; set; } 23 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/NavigationService.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using DbToys.Helpers; 3 | using DbToys.ViewModels; 4 | using Microsoft.UI.Xaml.Controls; 5 | using Microsoft.UI.Xaml.Navigation; 6 | 7 | namespace DbToys.Services; 8 | 9 | // For more information on navigation between pages see 10 | // https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/navigation.md 11 | public class NavigationService : INavigationService 12 | { 13 | private readonly IPageService _pageService; 14 | private object _lastParameterUsed; 15 | private Frame _frame; 16 | 17 | public event NavigatedEventHandler Navigated; 18 | 19 | public Frame Frame 20 | { 21 | get 22 | { 23 | if (_frame == null) 24 | { 25 | _frame = App.MainWindow.Content as Frame; 26 | RegisterFrameEvents(); 27 | } 28 | 29 | return _frame; 30 | } 31 | 32 | set 33 | { 34 | UnregisterFrameEvents(); 35 | _frame = value; 36 | RegisterFrameEvents(); 37 | } 38 | } 39 | 40 | [MemberNotNullWhen(true, nameof(Frame), nameof(_frame))] 41 | public bool CanGoBack => Frame != null && Frame.CanGoBack; 42 | 43 | public NavigationService(IPageService pageService) 44 | { 45 | _pageService = pageService; 46 | } 47 | 48 | private void RegisterFrameEvents() 49 | { 50 | if (_frame != null) 51 | { 52 | _frame.Navigated += OnNavigated; 53 | } 54 | } 55 | 56 | private void UnregisterFrameEvents() 57 | { 58 | if (_frame != null) 59 | { 60 | _frame.Navigated -= OnNavigated; 61 | } 62 | } 63 | 64 | public bool GoBack() 65 | { 66 | if (CanGoBack) 67 | { 68 | var vmBeforeNavigation = _frame.GetPageViewModel(); 69 | _frame.GoBack(); 70 | if (vmBeforeNavigation is INavigationAware navigationAware) 71 | { 72 | navigationAware.OnNavigatedFrom(); 73 | } 74 | 75 | return true; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | public bool NavigateTo(string pageKey, object parameter = null, bool clearNavigation = false) 82 | { 83 | var pageType = _pageService.GetPageType(pageKey); 84 | 85 | if (_frame != null && (_frame.Content?.GetType() != pageType || (parameter != null && !parameter.Equals(_lastParameterUsed)))) 86 | { 87 | _frame.Tag = clearNavigation; 88 | var vmBeforeNavigation = _frame.GetPageViewModel(); 89 | var navigated = _frame.Navigate(pageType, parameter); 90 | if (navigated) 91 | { 92 | _lastParameterUsed = parameter; 93 | if (vmBeforeNavigation is INavigationAware navigationAware) 94 | { 95 | navigationAware.OnNavigatedFrom(); 96 | } 97 | } 98 | 99 | return navigated; 100 | } 101 | 102 | return false; 103 | } 104 | 105 | private void OnNavigated(object sender, NavigationEventArgs e) 106 | { 107 | if (sender is Frame frame) 108 | { 109 | var clearNavigation = (bool)frame.Tag; 110 | if (clearNavigation) 111 | { 112 | frame.BackStack.Clear(); 113 | } 114 | 115 | if (frame.GetPageViewModel() is INavigationAware navigationAware) 116 | { 117 | navigationAware.OnNavigatedTo(e.Parameter); 118 | } 119 | 120 | Navigated?.Invoke(sender, e); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/NavigationViewService.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using DbToys.Helpers; 3 | using DbToys.ViewModels; 4 | using Microsoft.UI.Xaml.Controls; 5 | 6 | namespace DbToys.Services; 7 | 8 | public class NavigationViewService : INavigationViewService 9 | { 10 | private readonly INavigationService _navigationService; 11 | 12 | private readonly IPageService _pageService; 13 | 14 | private NavigationView _navigationView; 15 | 16 | public IList MenuItems => _navigationView?.MenuItems; 17 | 18 | public object SettingsItem => _navigationView?.SettingsItem; 19 | 20 | public NavigationViewService(INavigationService navigationService, IPageService pageService) 21 | { 22 | _navigationService = navigationService; 23 | _pageService = pageService; 24 | } 25 | 26 | [MemberNotNull(nameof(_navigationView))] 27 | public void Initialize(NavigationView navigationView) 28 | { 29 | _navigationView = navigationView; 30 | _navigationView.BackRequested += OnBackRequested; 31 | _navigationView.ItemInvoked += OnItemInvoked; 32 | } 33 | 34 | public void UnregisterEvents() 35 | { 36 | if (_navigationView != null) 37 | { 38 | _navigationView.BackRequested -= OnBackRequested; 39 | _navigationView.ItemInvoked -= OnItemInvoked; 40 | } 41 | } 42 | 43 | public NavigationViewItem GetSelectedItem(Type pageType) 44 | { 45 | if (_navigationView != null) 46 | { 47 | return GetSelectedItem(_navigationView.MenuItems, pageType) ?? GetSelectedItem(_navigationView.FooterMenuItems, pageType); 48 | } 49 | 50 | return null; 51 | } 52 | 53 | private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) => _navigationService.GoBack(); 54 | 55 | private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) 56 | { 57 | if (args.IsSettingsInvoked) 58 | { 59 | _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!); 60 | } 61 | else 62 | { 63 | var selectedItem = args.InvokedItemContainer as NavigationViewItem; 64 | 65 | if (selectedItem?.GetValue(NavigationHelper.NavigateToProperty) is string pageKey) 66 | { 67 | _navigationService.NavigateTo(pageKey); 68 | } 69 | } 70 | } 71 | 72 | private NavigationViewItem GetSelectedItem(IEnumerable menuItems, Type pageType) 73 | { 74 | foreach (var item in menuItems.OfType()) 75 | { 76 | if (IsMenuItemForPageType(item, pageType)) 77 | { 78 | return item; 79 | } 80 | 81 | var selectedChild = GetSelectedItem(item.MenuItems, pageType); 82 | if (selectedChild != null) 83 | { 84 | return selectedChild; 85 | } 86 | } 87 | 88 | return null; 89 | } 90 | 91 | private bool IsMenuItemForPageType(NavigationViewItem menuItem, Type sourcePageType) 92 | { 93 | if (menuItem.GetValue(NavigationHelper.NavigateToProperty) is string pageKey) 94 | { 95 | return _pageService.GetPageType(pageKey) == sourcePageType; 96 | } 97 | 98 | return false; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/PageService.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DbToys.ViewModels; 3 | using DbToys.Views; 4 | using Microsoft.UI.Xaml.Controls; 5 | 6 | namespace DbToys.Services; 7 | 8 | public class PageService : IPageService 9 | { 10 | private readonly Dictionary _pages = new(); 11 | 12 | public PageService() 13 | { 14 | Configure(); 15 | Configure(); 16 | Configure(); 17 | Configure(); 18 | Configure(); 19 | } 20 | 21 | public Type GetPageType(string key) 22 | { 23 | Type pageType; 24 | lock (_pages) 25 | { 26 | if (!_pages.TryGetValue(key, out pageType)) 27 | { 28 | throw new ArgumentException($"Page not found: {key}. Did you forget to call PageService.Configure?"); 29 | } 30 | } 31 | 32 | return pageType; 33 | } 34 | 35 | private void Configure() 36 | where VM : ObservableObject 37 | where V : Page 38 | { 39 | lock (_pages) 40 | { 41 | var key = typeof(VM).FullName!; 42 | if (_pages.ContainsKey(key)) 43 | { 44 | throw new ArgumentException($"The key {key} is already configured in PageService"); 45 | } 46 | 47 | var type = typeof(V); 48 | if (_pages.Any(p => p.Value == type)) 49 | { 50 | throw new ArgumentException($"This type is already configured with key {_pages.First(p => p.Value == type).Key}"); 51 | } 52 | 53 | _pages.Add(key, type); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/FileService.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using DbToys.Helpers; 3 | 4 | namespace DbToys.Services.Settings; 5 | 6 | public class FileService : IFileService 7 | { 8 | public T Read(string folderPath, string fileName) 9 | { 10 | ArgumentException.ThrowIfNullOrEmpty(folderPath); 11 | ArgumentException.ThrowIfNullOrEmpty(fileName); 12 | var path = Path.Combine(folderPath, fileName); 13 | if (File.Exists(path)) 14 | { 15 | var json = File.ReadAllText(path); 16 | return Json.Deserialize(json); 17 | } 18 | 19 | return default; 20 | } 21 | 22 | public void Save(string folderPath, string fileName, T content) 23 | { 24 | ArgumentException.ThrowIfNullOrEmpty(folderPath); 25 | ArgumentException.ThrowIfNullOrEmpty(fileName); 26 | if (!Directory.Exists(folderPath)) 27 | { 28 | Directory.CreateDirectory(folderPath); 29 | } 30 | 31 | var fileContent = Json.Serialize(content); 32 | File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, Encoding.UTF8); 33 | } 34 | 35 | public void Delete(string folderPath, string fileName) 36 | { 37 | ArgumentException.ThrowIfNullOrEmpty(folderPath); 38 | ArgumentException.ThrowIfNullOrEmpty(fileName); 39 | if (File.Exists(Path.Combine(folderPath, fileName))) 40 | { 41 | File.Delete(Path.Combine(folderPath, fileName)); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/GeneralSettingsService.cs: -------------------------------------------------------------------------------- 1 |  2 | using DbToys.Core; 3 | 4 | namespace DbToys.Services.Settings; 5 | 6 | public class GeneralSettingsService : SettingsServiceBase 7 | { 8 | public GeneralSettingsService(IFileService fileService) 9 | : base(fileService) 10 | { 11 | } 12 | 13 | public override string SettingFileName { get; set; } = Constants.LocalSettings.GeneralSettingsFileName; 14 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/IFileService.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services.Settings; 2 | 3 | public interface IFileService 4 | { 5 | T Read(string folderPath, string fileName); 6 | 7 | void Save(string folderPath, string fileName, T content); 8 | 9 | void Delete(string folderPath, string fileName); 10 | } 11 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/ISettingsService.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.Services.Settings; 2 | 3 | public interface ISettingsService 4 | { 5 | string SettingFileName { get; set; } 6 | 7 | T GetValue(string key); 8 | 9 | void SetValue(string key, T value); 10 | 11 | Task GetValueAsync(string key); 12 | 13 | Task SetValueAsync(string key, T value); 14 | } 15 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/SettingsServiceBase.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | using Windows.Storage; 4 | using DbToys.Helpers; 5 | 6 | namespace DbToys.Services.Settings; 7 | 8 | public abstract class SettingsServiceBase : ISettingsService 9 | { 10 | [JsonIgnore] 11 | public abstract string SettingFileName { get; set; } 12 | 13 | private readonly IFileService _fileService; 14 | 15 | private readonly string _applicationDataFolder; 16 | 17 | private IDictionary _settings; 18 | 19 | private bool _isInitialized; 20 | 21 | protected SettingsServiceBase(IFileService fileService) 22 | { 23 | _fileService = fileService; 24 | 25 | _applicationDataFolder = FileSystemHelper.GetDbToysAppDataFolder(); 26 | _settings = new Dictionary(); 27 | } 28 | 29 | protected virtual void Initialize() 30 | { 31 | if (!_isInitialized) 32 | { 33 | _settings = _fileService.Read>(_applicationDataFolder, SettingFileName) ?? new Dictionary(); 34 | 35 | _isInitialized = true; 36 | } 37 | } 38 | 39 | protected virtual async Task InitializeAsync() 40 | { 41 | if (!_isInitialized) 42 | { 43 | _settings = await Task.Run(() => _fileService.Read>(_applicationDataFolder, SettingFileName)) ?? new Dictionary(); 44 | 45 | _isInitialized = true; 46 | } 47 | } 48 | 49 | public T GetValue(string key) 50 | { 51 | if (RuntimeHelper.IsMSIX) 52 | { 53 | if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj)) 54 | { 55 | return Json.Deserialize(obj.ToString()); 56 | } 57 | } 58 | else 59 | { 60 | Initialize(); 61 | 62 | if (_settings == null || !_settings.TryGetValue(key, out var obj)) return default; 63 | 64 | if (obj is JsonElement jElem) 65 | { 66 | return jElem.Deserialize(); 67 | } 68 | 69 | return (T)obj; 70 | } 71 | 72 | return default; 73 | } 74 | 75 | public void SetValue(string key, T value) 76 | { 77 | if (RuntimeHelper.IsMSIX) 78 | { 79 | ApplicationData.Current.LocalSettings.Values[key] = Json.Serialize(value); 80 | } 81 | else 82 | { 83 | Initialize(); 84 | 85 | _settings[key] = value; 86 | 87 | _fileService.Save(_applicationDataFolder, SettingFileName, _settings); 88 | } 89 | } 90 | 91 | public async Task GetValueAsync(string key) 92 | { 93 | if (RuntimeHelper.IsMSIX) 94 | { 95 | if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj)) 96 | { 97 | return await Json.DeserializeAsync(obj.ToString()); 98 | } 99 | } 100 | else 101 | { 102 | await InitializeAsync(); 103 | 104 | if (_settings == null || !_settings.TryGetValue(key, out var obj)) return default; 105 | 106 | if (obj is JsonElement jElem) 107 | { 108 | return jElem.Deserialize(); 109 | } 110 | 111 | return (T)obj; 112 | } 113 | 114 | return default; 115 | } 116 | 117 | public async Task SetValueAsync(string key, T value) 118 | { 119 | if (RuntimeHelper.IsMSIX) 120 | { 121 | ApplicationData.Current.LocalSettings.Values[key] = await Json.SerializeAsync(value); 122 | } 123 | else 124 | { 125 | await InitializeAsync(); 126 | 127 | _settings[key] = value; 128 | 129 | await Task.Run(() => _fileService.Save(_applicationDataFolder, SettingFileName, _settings)); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/Settings/UiSettingsService.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Core; 2 | 3 | namespace DbToys.Services.Settings; 4 | 5 | public class UiSettingsService : SettingsServiceBase 6 | { 7 | public override string SettingFileName { get; set; } = Constants.LocalSettings.UiSettingsFileName; 8 | 9 | public string CodeGeneratorTemplateProject 10 | { 11 | get => GetValue(nameof(CodeGeneratorTemplateProject)); 12 | set => SetValue(nameof(CodeGeneratorTemplateProject), value); 13 | } 14 | 15 | public string CodeGeneratorOutputPath 16 | { 17 | get => GetValue(nameof(CodeGeneratorOutputPath)); 18 | set => SetValue(nameof(CodeGeneratorOutputPath), value); 19 | } 20 | 21 | public UiSettingsService(IFileService fileService) : base(fileService) { } 22 | 23 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Services/ThemeSelectorService.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Helpers; 2 | using DbToys.Services.Settings; 3 | using Microsoft.UI.Xaml; 4 | 5 | namespace DbToys.Services; 6 | 7 | public class ThemeSelectorService : IThemeSelectorService 8 | { 9 | private const string SettingsKey = "AppBackgroundRequestedTheme"; 10 | 11 | public ElementTheme Theme { get; set; } = ElementTheme.Default; 12 | 13 | private readonly GeneralSettingsService _settingsService; 14 | 15 | public ThemeSelectorService(GeneralSettingsService settingsService) 16 | { 17 | _settingsService = settingsService; 18 | } 19 | 20 | public async Task InitializeAsync() 21 | { 22 | Theme = await LoadThemeFromSettingsAsync(); 23 | await Task.CompletedTask; 24 | } 25 | 26 | public async Task SetThemeAsync(ElementTheme theme) 27 | { 28 | Theme = theme; 29 | 30 | await SetRequestedThemeAsync(); 31 | await SaveThemeInSettingsAsync(Theme); 32 | } 33 | 34 | public async Task SetRequestedThemeAsync() 35 | { 36 | if (App.MainWindow.Content is FrameworkElement rootElement) 37 | { 38 | rootElement.RequestedTheme = Theme; 39 | 40 | TitleBarHelper.UpdateTitleBar(Theme); 41 | } 42 | 43 | await Task.CompletedTask; 44 | } 45 | 46 | private async Task LoadThemeFromSettingsAsync() 47 | { 48 | var themeName = await _settingsService.GetValueAsync(SettingsKey); 49 | 50 | if (Enum.TryParse(themeName, out ElementTheme cacheTheme)) 51 | { 52 | return cacheTheme; 53 | } 54 | 55 | return ElementTheme.Default; 56 | } 57 | 58 | private async Task SaveThemeInSettingsAsync(ElementTheme theme) 59 | { 60 | await _settingsService.SetValueAsync(SettingsKey, theme.ToString()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Styles/Colors.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | #1677ff 10 | #52c41a 11 | #13c2c2 12 | #faad14 13 | #f5222d 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | #FF333333 24 | #FF444444 25 | #FF555555 26 | #FFDDDDDD 27 | #FFF0F0F0 28 | 30 | 32 | 34 | 36 | 38 | 39 | 40 | #FFF0F0F0 41 | #FFDDDDDD 42 | #FF555555 43 | #FF444444 44 | #FF333333 45 | 47 | 49 | 51 | 53 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Styles/FontSizes.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 24 6 | 7 | 16 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Styles/TextBlock.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 12 | 13 | 19 | 20 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Styles/Thickness.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 0,36,0,0 6 | 0,36,0,36 7 | 8 | 0,24,0,0 9 | 0,24,0,24 10 | 24,0,24,0 11 | 0,0,0,24 12 | 13 | 12,0,0,0 14 | 12,0,12,0 15 | 0,12,0,0 16 | 0,0,12,0 17 | 0,12,0,12 18 | 19 | 8,0,0,0 20 | 0,0,8,0 21 | 0,8,0,0 22 | 8,8,8,8 23 | 24 | 4,0,0,0 25 | 0,0,4,0 26 | 0,4,0,0 27 | 4,4,4,4 28 | 29 | 1,1,0,0 30 | 8,0,0,0 31 | 0,48,0,0 32 | 24,24,0,0 33 | 16,16,24,0 34 | 35 | 36,24,36,0 36 | 37 | -12,4,0,0 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/TemplateStudio.xml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Usings.cs: -------------------------------------------------------------------------------- 1 | global using WinUIEx; 2 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/CodeTemplate/ActionArgs.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | 3 | namespace DbToys.ViewModels.CodeTemplate; 4 | 5 | public record RenamedArgs(string OldName, string NewName, string OldPath, string NewPath); 6 | 7 | public record ProjectDeletedArg(string FolderName, string FolderPath); 8 | 9 | public record ProjectCreatedArg(StorageFolder Folder); 10 | 11 | public record TemplateCreatedArg(StorageFile File); 12 | 13 | public record TemplateDeletedArg(string FileName, string FilePath, string FolderName, string FolderPath); 14 | 15 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/CodeTemplate/TemplateFileItem.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | using Windows.Storage.FileProperties; 3 | using CommunityToolkit.Mvvm.Input; 4 | using DbToys.Core; 5 | using DbToys.Helpers; 6 | using DbToys.Services; 7 | using Microsoft.UI.Xaml.Controls; 8 | using Microsoft.UI.Xaml.Media; 9 | using Microsoft.UI.Xaml.Media.Imaging; 10 | 11 | namespace DbToys.ViewModels.CodeTemplate; 12 | 13 | public class TemplateFileItem : TreeItem 14 | { 15 | private readonly Lazy _notificationService = new(App.GetService); 16 | 17 | private ImageSource _icon; 18 | public ImageSource Icon { get => _icon; set => SetProperty(ref _icon, value); } 19 | 20 | public StorageFile File { get; set; } 21 | 22 | public StorageFolder Folder { get; set; } 23 | 24 | public string TabDisplayName => $"{Folder.Name}\\{File.Name}"; 25 | 26 | public Action RenamedAction { get; set; } 27 | 28 | public Action DeletedAction { get; set; } 29 | 30 | public IAsyncRelayCommand RenameCommand { get; set; } 31 | 32 | public IAsyncRelayCommand DeleteCommand { get; set; } 33 | 34 | public TemplateFileItem(StorageFile file, StorageFolder folder) : base(file.Name) 35 | { 36 | File = file; 37 | Folder = folder; 38 | RenameCommand = new AsyncRelayCommand(RenameAsync); 39 | DeleteCommand = new AsyncRelayCommand(DeleteAsync); 40 | LoadIcon(); 41 | } 42 | 43 | private async Task DeleteAsync() 44 | { 45 | var dialog = DialogFactory.GetFor_DeleteTemplateConfirmDialog(); 46 | await dialog.ShowAsync(); 47 | if (dialog.ViewModel.DialogResult != ContentDialogResult.Primary) 48 | return; 49 | 50 | await File.DeleteAsync(); 51 | DeletedAction?.Invoke(new TemplateDeletedArg(File.Name, File.Path, Folder.Name, Folder.Path)); 52 | } 53 | 54 | private async Task RenameAsync() 55 | { 56 | var oldName = File.Name; 57 | var oldPath = File.Path; 58 | string input; 59 | 60 | var templateFileExtension = Constants.FileSystem.CodeTemplateFileExtension; 61 | 62 | if (oldName.EndsWith(templateFileExtension)) 63 | { 64 | input = oldName 65 | .Remove(oldName.Length - templateFileExtension.Length, templateFileExtension.Length); 66 | } 67 | else 68 | { 69 | input = oldName; 70 | } 71 | var dialog = DialogFactory.GetFor_RenameDialog(input); 72 | await dialog.ShowAsync(); 73 | 74 | string newName; 75 | if (dialog.ViewModel.DialogResult == ContentDialogResult.Primary) 76 | { 77 | input = (string)dialog.ViewModel.AdditionalData; 78 | if (input.EndsWith(Constants.FileSystem.CodeTemplateFileExtension)) 79 | { 80 | newName = input; 81 | } 82 | else 83 | { 84 | newName = input + Constants.FileSystem.CodeTemplateFileExtension; 85 | } 86 | } 87 | else return; 88 | 89 | if (string.IsNullOrEmpty(newName) || oldName == newName) return; 90 | try 91 | { 92 | await File.RenameAsync(newName, NameCollisionOption.FailIfExists); 93 | // newName = File.Name; // Unique name may be generated 94 | } 95 | catch (Exception ex) 96 | { 97 | _notificationService.Value.Error($"Rename template file failed with error: {ex.Message}"); 98 | return; 99 | } 100 | RenamedAction?.Invoke(new RenamedArgs(oldName, newName, oldPath, File.Path)); 101 | } 102 | 103 | public async void LoadIcon() 104 | { 105 | var thumbnail = await File.GetThumbnailAsync(ThumbnailMode.ListView, 32, ThumbnailOptions.UseCurrentScale); 106 | var img = new BitmapImage(); 107 | img.SetSource(thumbnail); 108 | Icon = img; 109 | } 110 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/CodeTemplate/TemplateViewModel.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | using Windows.Storage.Streams; 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | using DbToys.Services; 5 | 6 | namespace DbToys.ViewModels.CodeTemplate; 7 | 8 | public class TemplateViewModel : ObservableObject 9 | { 10 | public StorageFile File { get; set; } 11 | 12 | private readonly Lazy _notificationService = new(App.GetService); 13 | 14 | public async Task ReadTextAsync() 15 | { 16 | if (File == null) return string.Empty; 17 | return await FileIO.ReadTextAsync(File, UnicodeEncoding.Utf8); 18 | } 19 | 20 | public async void SaveText(string text) 21 | { 22 | try 23 | { 24 | await FileIO.WriteTextAsync(File, text); 25 | } 26 | catch (Exception ex) 27 | { 28 | _notificationService.Value.Error($"Save file failed: {ex.Message}"); 29 | return; 30 | } 31 | _notificationService.Value.Success("File saved"); 32 | } 33 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/CodeTemplateExplorerViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using Windows.Storage; 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | using CommunityToolkit.Mvvm.Input; 7 | using DbToys.Helpers; 8 | using DbToys.Services; 9 | using DbToys.ViewModels.CodeTemplate; 10 | using Microsoft.UI.Xaml.Controls; 11 | 12 | namespace DbToys.ViewModels; 13 | 14 | public class CodeTemplateExplorerViewModel : ObservableRecipient 15 | { 16 | private object _selectedItem; 17 | public object SelectedItem 18 | { 19 | get => _selectedItem; 20 | set => SetProperty(ref _selectedItem, value); 21 | } 22 | 23 | public ObservableCollection TreeItems = new(); 24 | 25 | private readonly INotificationService _notificationService; 26 | private readonly CodeTemplateStorageService _templateStorageService; 27 | 28 | public IRelayCommand ReloadCommand { get; set; } 29 | public IAsyncRelayCommand CreateProjectCommand { get; set; } 30 | public IRelayCommand ExplorerCommand { get; set; } 31 | 32 | public Action ReloadAction { get; set; } 33 | 34 | public Action ProjectCreatedAction { get; set; } 35 | 36 | public CodeTemplateExplorerViewModel(INotificationService notificationService, CodeTemplateStorageService templateStorageService) 37 | { 38 | _notificationService = notificationService; 39 | _templateStorageService = templateStorageService; 40 | CreateProjectCommand = new AsyncRelayCommand(CreateProjectAsync); 41 | ReloadCommand = new RelayCommand(ReloadProjectTree); 42 | ExplorerCommand = new RelayCommand(ShowInExplorer); 43 | } 44 | 45 | private void ShowInExplorer() 46 | { 47 | try 48 | { 49 | Process.Start("explorer.exe", _templateStorageService.TemplateFolderPath); 50 | } 51 | catch (Win32Exception win32Exception) 52 | { 53 | _notificationService.Error(win32Exception.Message); 54 | } 55 | } 56 | 57 | private async Task CreateProjectAsync() 58 | { 59 | var dialog = DialogFactory.GetFor_CreateProjectDialog(); 60 | await dialog.ShowAsync(); 61 | string folderName; 62 | if (dialog.ViewModel.DialogResult == ContentDialogResult.Primary) 63 | { 64 | folderName = (string)dialog.ViewModel.AdditionalData; 65 | } 66 | else return; 67 | 68 | if (string.IsNullOrEmpty(folderName)) return; 69 | StorageFolder folder; 70 | try 71 | { 72 | folder = await _templateStorageService.CreateProjectFolder(folderName); 73 | } 74 | catch (Exception ex) 75 | { 76 | _notificationService.Error($"Create project folder failed with error: {ex.Message}"); 77 | return; 78 | } 79 | if(folder == null ) return; 80 | ProjectCreatedAction?.Invoke(new ProjectCreatedArg(folder)); 81 | } 82 | 83 | public void ReloadProjectTree() 84 | { 85 | ReloadAction?.Invoke(); 86 | } 87 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/Database/ConnectionItem.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Core.Database; 2 | 3 | namespace DbToys.ViewModels.Database; 4 | 5 | public class ConnectionItem : TreeItem 6 | { 7 | private DatabaseType _databaseType; 8 | public DatabaseType DatabaseType { get => _databaseType; set => SetProperty(ref _databaseType, value); } 9 | 10 | public ConnectionItem(string name, DatabaseType databaseType) : base(name, false) 11 | { 12 | DatabaseType=databaseType; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/DatabaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | using CommunityToolkit.Mvvm.Input; 4 | using DbToys.Core.Database; 5 | using DbToys.Services; 6 | using DbToys.ViewModels.Database; 7 | using DbToys.Views.Dialogs; 8 | 9 | namespace DbToys.ViewModels; 10 | 11 | public class DatabaseViewModel : ObservableObject 12 | { 13 | private readonly INotificationService _notificationService; 14 | 15 | public IAsyncRelayCommand ConnectCommand { get; } 16 | 17 | public ISchemaReader SchemaReader { get; private set; } 18 | 19 | private ObservableCollection _connectionItems = new(); 20 | public ObservableCollection ConnectionItems 21 | { 22 | get => _connectionItems; 23 | set => SetProperty(ref _connectionItems, value); 24 | } 25 | 26 | private object _selectedItem; 27 | public object SelectedItem 28 | { 29 | get => _selectedItem; 30 | set => SetProperty(ref _selectedItem, value); 31 | } 32 | 33 | public DatabaseViewModel(INotificationService notificationService) 34 | { 35 | _notificationService = notificationService; 36 | ConnectCommand = new AsyncRelayCommand(ConnectDatabase); 37 | } 38 | 39 | private async Task ConnectDatabase(string dbType) 40 | { 41 | if (dbType == "PostgreSql") 42 | { 43 | var dialog = App.GetService(); 44 | dialog.XamlRoot = App.MainWindow.Content.XamlRoot; 45 | await dialog.ShowAsync(); 46 | if (dialog.ViewModel.SchemaReader != null) 47 | { 48 | SchemaReader = dialog.ViewModel.SchemaReader; 49 | LoadDatabaseTreeNode(SchemaReader, DatabaseType.PostgreSql); 50 | } 51 | } 52 | else if (dbType == "MySql") 53 | { 54 | var dialog = App.GetService(); 55 | dialog.XamlRoot = App.MainWindow.Content.XamlRoot; 56 | await dialog.ShowAsync(); 57 | if (dialog.ViewModel.SchemaReader != null) 58 | { 59 | SchemaReader = dialog.ViewModel.SchemaReader; 60 | LoadDatabaseTreeNode(SchemaReader, DatabaseType.Mysql); 61 | } 62 | } 63 | else if (dbType == "SqlServer") 64 | { 65 | var dialog = App.GetService(); 66 | dialog.XamlRoot = App.MainWindow.Content.XamlRoot; 67 | await dialog.ShowAsync(); 68 | if (dialog.ViewModel.SchemaReader != null) 69 | { 70 | SchemaReader = dialog.ViewModel.SchemaReader; 71 | LoadDatabaseTreeNode(SchemaReader, DatabaseType.SqlServer); 72 | } 73 | } 74 | } 75 | 76 | private void LoadDatabaseTreeNode(ISchemaReader schemaReader, DatabaseType dbType) 77 | { 78 | // issue: may case crash https://github.com/microsoft/microsoft-ui-xaml/issues/2121 79 | ConnectionItems.Clear(); 80 | var item = new ConnectionItem(schemaReader.GetServerName(), dbType); 81 | try 82 | { 83 | var dbs = schemaReader.ReadDatabases(); 84 | foreach (var db in dbs) 85 | { 86 | item.AddChild(new DatabaseItem(db, schemaReader)); 87 | } 88 | } 89 | catch (Exception ex) 90 | { 91 | _notificationService.Error(ex.Message, "Read database schema failed"); 92 | } 93 | ConnectionItems.Add(item); 94 | item.ExpandPath(); 95 | } 96 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/Dialogs/GenerateCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using Windows.Storage; 3 | using Windows.Storage.Pickers; 4 | using CommunityToolkit.Mvvm.ComponentModel; 5 | using CommunityToolkit.Mvvm.Input; 6 | using DbToys.Core; 7 | using DbToys.Helpers; 8 | using DbToys.Services; 9 | using DbToys.Services.Settings; 10 | using Microsoft.UI.Xaml; 11 | using Microsoft.UI.Xaml.Controls; 12 | 13 | namespace DbToys.ViewModels.Dialogs; 14 | 15 | public class GenerateCodeViewModel : ObservableRecipient 16 | { 17 | private readonly CodeTemplateStorageService _storageService; 18 | private readonly UiSettingsService _uiSettingsService; 19 | 20 | public IRelayCommand ConfirmCommand { get; set; } 21 | 22 | private int _selectedProjectIndex; 23 | public int SelectedProjectIndex 24 | { 25 | get => _selectedProjectIndex; 26 | set => SetProperty(ref _selectedProjectIndex, value); 27 | } 28 | 29 | private StorageFolder _templateProjectFolder; 30 | public StorageFolder TemplateProjectFolder 31 | { 32 | get => _templateProjectFolder; 33 | set => SetProperty(ref _templateProjectFolder, value); 34 | } 35 | 36 | public ContentDialogResult DialogResult { get; private set; } 37 | 38 | private string _outputPath; 39 | public string OutputPath { get => _outputPath; set => SetProperty(ref _outputPath, value); } 40 | 41 | public IAsyncRelayCommand PickOutputFolderCommand { get; set; } 42 | 43 | public ObservableCollection ProjectFolders { get; set; } = new(); 44 | 45 | public GenerateCodeViewModel(CodeTemplateStorageService storageService, UiSettingsService uiSettingsService) 46 | { 47 | _storageService = storageService; 48 | _uiSettingsService = uiSettingsService; 49 | PickOutputFolderCommand = new AsyncRelayCommand(PickOutputFolder); 50 | ConfirmCommand = new RelayCommand(OnConfirm); 51 | } 52 | 53 | private void OnConfirm() 54 | { 55 | if (_uiSettingsService.CodeGeneratorOutputPath != OutputPath && !string.IsNullOrEmpty(OutputPath)) 56 | _uiSettingsService.CodeGeneratorOutputPath = OutputPath; 57 | 58 | if (TemplateProjectFolder != null && 59 | _uiSettingsService.CodeGeneratorTemplateProject != TemplateProjectFolder.Name) 60 | _uiSettingsService.CodeGeneratorTemplateProject = TemplateProjectFolder.Name; 61 | 62 | DialogResult = ContentDialogResult.Primary; 63 | } 64 | 65 | private async Task PickOutputFolder() 66 | { 67 | var folderPicker = new FolderPicker { SuggestedStartLocation = PickerLocationId.Desktop }; 68 | 69 | // When running on win32, FileOpenPicker needs to know the top-level hwnd via IInitializeWithWindow::Initialize. 70 | if (Window.Current == null) 71 | { 72 | WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, Win32Helper.GetActiveWindow()); 73 | } 74 | 75 | var outputFolder = await folderPicker.PickSingleFolderAsync(); 76 | if (outputFolder != null) 77 | { 78 | OutputPath = outputFolder.Path; 79 | } 80 | } 81 | 82 | protected override async void OnActivated() 83 | { 84 | OutputPath = _uiSettingsService.CodeGeneratorOutputPath; 85 | var folders = await _storageService.GetProjectFoldersAsync(); 86 | if (folders is { Count: > 0 }) 87 | { 88 | foreach (var storageFolder in folders) 89 | { 90 | if (storageFolder.Name == Constants.CodeTemplate.DefaultGlobalTemplateFolderName) continue; 91 | ProjectFolders.Add(storageFolder); 92 | } 93 | 94 | foreach (var fo in ProjectFolders) 95 | { 96 | if (fo.Name != _uiSettingsService.CodeGeneratorTemplateProject) continue; 97 | TemplateProjectFolder = fo; 98 | break; 99 | } 100 | 101 | if (TemplateProjectFolder == null) TemplateProjectFolder = ProjectFolders[0]; 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/Dialogs/IDialog.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Microsoft.UI.Xaml.Controls; 3 | 4 | namespace DbToys.ViewModels.Dialogs; 5 | 6 | public interface IDialog where TViewModel : class, INotifyPropertyChanged 7 | { 8 | TViewModel ViewModel { get; set; } 9 | 10 | Task ShowAsync(); 11 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/Dialogs/TemplateFilenameViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace DbToys.ViewModels.Dialogs; 4 | 5 | public class TemplateFilenameViewModel : ObservableObject 6 | { 7 | private string _title; 8 | public string Title { get => _title; set => SetProperty(ref _title, value); } 9 | 10 | private string _filename; 11 | public string Filename { get => _filename; set => SetProperty(ref _filename, value); } 12 | 13 | private bool _canConfirm; 14 | public bool CanConfirm { get => _canConfirm; set => SetProperty(ref _canConfirm, value); } 15 | 16 | public TemplateFilenameViewModel() 17 | { 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/INavigationAware.cs: -------------------------------------------------------------------------------- 1 | namespace DbToys.ViewModels; 2 | 3 | public interface INavigationAware 4 | { 5 | void OnNavigatedTo(object parameter); 6 | 7 | void OnNavigatedFrom(); 8 | } 9 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/LogViewModel.cs: -------------------------------------------------------------------------------- 1 | using Windows.Storage; 2 | using Windows.Storage.Search; 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | using DbToys.Core.Log; 5 | 6 | namespace DbToys.ViewModels; 7 | 8 | public class LogViewModel : ObservableRecipient, INavigationAware 9 | { 10 | private string _message; 11 | public string Message { get => _message; set => SetProperty(ref _message, value); } 12 | 13 | private StorageFolder _folder; 14 | 15 | //public IAsyncRelayCommand ReadLogCommand { get; set; } 16 | 17 | public LogViewModel() 18 | { 19 | // ReadLogCommand = new AsyncRelayCommand(ReadLogAsync); 20 | } 21 | 22 | protected override void OnActivated() 23 | { 24 | 25 | } 26 | 27 | public async void ReadLogAsync() 28 | { 29 | try 30 | { 31 | if (_folder == null) 32 | { 33 | _folder = await StorageFolder.GetFolderFromPathAsync(Logger.ApplicationLogPath); 34 | } 35 | 36 | if (_folder == null) return; 37 | var files = await _folder.GetFilesAsync(CommonFileQuery.OrderByName); 38 | if (files == null || files.Count == 0) return; 39 | var logFile = files.Last(); 40 | Message = await FileIO.ReadTextAsync(logFile); 41 | } 42 | catch (Exception ex) 43 | { 44 | Logger.Error(ex.Message, ex); 45 | } 46 | } 47 | 48 | public void OnNavigatedTo(object parameter) 49 | { 50 | ReadLogAsync(); 51 | } 52 | 53 | public void OnNavigatedFrom() 54 | { 55 | } 56 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace DbToys.ViewModels; 4 | 5 | public class MainViewModel : ObservableRecipient 6 | { 7 | public MainViewModel() 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/ShellViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DbToys.Services; 3 | using DbToys.Views; 4 | using Microsoft.UI.Xaml.Navigation; 5 | 6 | namespace DbToys.ViewModels; 7 | 8 | public class ShellViewModel : ObservableRecipient 9 | { 10 | private bool _isBackEnabled; 11 | private object _selected; 12 | 13 | public INavigationService NavigationService 14 | { 15 | get; 16 | } 17 | 18 | public INavigationViewService NavigationViewService 19 | { 20 | get; 21 | } 22 | 23 | public bool IsBackEnabled 24 | { 25 | get => _isBackEnabled; 26 | set => SetProperty(ref _isBackEnabled, value); 27 | } 28 | 29 | public object Selected 30 | { 31 | get => _selected; 32 | set => SetProperty(ref _selected, value); 33 | } 34 | 35 | public ShellViewModel(INavigationService navigationService, INavigationViewService navigationViewService) 36 | { 37 | NavigationService = navigationService; 38 | NavigationService.Navigated += OnNavigated; 39 | NavigationViewService = navigationViewService; 40 | } 41 | 42 | private void OnNavigated(object sender, NavigationEventArgs e) 43 | { 44 | IsBackEnabled = NavigationService.CanGoBack; 45 | 46 | if (e.SourcePageType == typeof(SettingsPage)) 47 | { 48 | Selected = NavigationViewService.SettingsItem; 49 | return; 50 | } 51 | 52 | var selectedItem = NavigationViewService.GetSelectedItem(e.SourcePageType); 53 | if (selectedItem != null) 54 | { 55 | Selected = selectedItem; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/TableDetailViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System.Collections.ObjectModel; 3 | using System.Data; 4 | using DbToys.Core.Database; 5 | using DbToys.Services; 6 | using Microsoft.UI.Dispatching; 7 | 8 | namespace DbToys.ViewModels; 9 | 10 | public class TableDetailViewModel : ObservableRecipient 11 | { 12 | public Table SelectedTable { get; set; } 13 | 14 | public ObservableCollection TableResultSet { get; set; } = new(); 15 | 16 | public ObservableCollection TableColumns { get; set; } = new(); 17 | 18 | public ISchemaReader SchemaReader { get; set; } 19 | 20 | public Action OnResultSetLoaded; 21 | 22 | private readonly INotificationService _notificationService; 23 | 24 | public TableDetailViewModel(INotificationService notificationService) 25 | { 26 | _notificationService = notificationService; 27 | } 28 | 29 | protected override void OnActivated() 30 | { 31 | base.OnActivated(); 32 | InitData(); 33 | } 34 | 35 | protected override void OnDeactivated() 36 | { 37 | base.OnDeactivated(); 38 | TableResultSet = null; 39 | SchemaReader = null; 40 | TableColumns = null; 41 | SelectedTable = null; 42 | OnResultSetLoaded = null; 43 | } 44 | 45 | private void InitData() 46 | { 47 | var table = SelectedTable; 48 | if (table == null) return; 49 | 50 | var dispatcherQueue = DispatcherQueue.GetForCurrentThread(); 51 | Task.Run(() => 52 | { 53 | List columns = null; 54 | DataTable resultSet = null; 55 | try 56 | { 57 | columns = SchemaReader?.ReadColumns(table.Database, table.Schema, 58 | table.Name); 59 | var firstPk = columns?.FirstOrDefault(t => t.IsPk); 60 | var sort = firstPk == null ? null : firstPk.Name + " desc"; 61 | resultSet = SchemaReader?.GetResultSet(table, 30, sort); 62 | } 63 | catch (Exception ex) 64 | { 65 | dispatcherQueue.TryEnqueue(() => 66 | { 67 | _notificationService.Error(ex.Message, "Read column info failed"); 68 | }); 69 | } 70 | 71 | dispatcherQueue.TryEnqueue(() => 72 | { 73 | TableColumns.Clear(); 74 | TableResultSet?.Clear(); 75 | columns?.ForEach(item => { TableColumns.Add(item); }); 76 | if (resultSet != null) 77 | { 78 | OnResultSetLoaded(resultSet.Columns); 79 | foreach (DataRow row in resultSet.Rows) 80 | { 81 | TableResultSet?.Add(row.ItemArray); 82 | } 83 | } 84 | }); 85 | }); 86 | } 87 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/ViewModels/TreeItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | 4 | namespace DbToys.ViewModels; 5 | 6 | 7 | public class TreeItem : ObservableRecipient 8 | { 9 | private string _name; 10 | public string Name 11 | { 12 | get => _name; 13 | set => SetProperty(ref _name, value); 14 | } 15 | 16 | public ObservableCollection Children { get; set; } 17 | 18 | private bool _isExpanded; 19 | public bool IsExpanded 20 | { 21 | get => _isExpanded; 22 | set 23 | { 24 | SetProperty(ref _isExpanded, value); 25 | // Lazy load the child items, if necessary. 26 | if (_isExpanded && HasUnrealizedChildren && Children.Count == 0) 27 | { 28 | LoadChildren(); 29 | } 30 | } 31 | } 32 | 33 | protected virtual void LoadChildren() 34 | { 35 | } 36 | 37 | private bool _isSelected; 38 | public bool IsSelected 39 | { 40 | get => _isSelected; 41 | set => SetProperty(ref _isSelected, value); 42 | } 43 | 44 | private bool _hasUnrealizedChildren; 45 | public bool HasUnrealizedChildren 46 | { 47 | get => _hasUnrealizedChildren; 48 | set => SetProperty(ref _hasUnrealizedChildren, value); 49 | } 50 | 51 | private TreeItem _parent; 52 | 53 | protected TreeItem(string name, bool lazyLoadChildren) 54 | { 55 | _name = name; 56 | Children = new ObservableCollection(); 57 | if (lazyLoadChildren) _hasUnrealizedChildren = true; 58 | } 59 | 60 | protected TreeItem(string name) 61 | 62 | { 63 | _name = name; 64 | } 65 | 66 | public void AddChild(TreeItem child) 67 | { 68 | child._parent = this; 69 | Children!.Add(child); 70 | } 71 | 72 | public void ExpandPath() 73 | { 74 | IsExpanded = true; 75 | _parent?.ExpandPath(); 76 | } 77 | 78 | public void CollapsePath() 79 | { 80 | IsExpanded = false; 81 | _parent?.CollapsePath(); 82 | } 83 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/CodeTemplate/TemplatePage.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/Dialogs/DynamicDialog.xaml: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 39 | 40 | 41 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/Dialogs/DynamicDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Helpers; 2 | using DbToys.ViewModels.Dialogs; 3 | using Microsoft.UI.Xaml.Controls; 4 | 5 | namespace DbToys.Views.Dialogs; 6 | 7 | public sealed partial class DynamicDialog 8 | { 9 | public DynamicDialog(DynamicDialogViewModel vm) 10 | { 11 | ViewModel = vm; 12 | InitializeComponent(); 13 | ViewModel.HideDialog = Hide; 14 | } 15 | 16 | public DynamicDialogViewModel ViewModel { get; set; } 17 | 18 | public new Task ShowAsync() => DialogHelper.SetContentDialogRoot(this).ShowAsync().AsTask(); 19 | 20 | private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 21 | { 22 | ViewModel.PrimaryButtonCommand.Execute(args); 23 | } 24 | 25 | private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 26 | { 27 | ViewModel.SecondaryButtonCommand.Execute(args); 28 | } 29 | 30 | private void ContentDialog_CloseButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) 31 | { 32 | ViewModel.CloseButtonCommand.Execute(args); 33 | } 34 | 35 | private void ContentDialog_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e) 36 | { 37 | ViewModel.KeyDownCommand.Execute(e); 38 | } 39 | } -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/Dialogs/GenerateCodeDialog.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/Dialogs/GenerateCodeDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using DbToys.Helpers; 2 | using DbToys.ViewModels.Dialogs; 3 | using Microsoft.UI.Xaml.Controls; 4 | 5 | namespace DbToys.Views.Dialogs 6 | { 7 | public sealed partial class GenerateCodeDialog 8 | { 9 | public GenerateCodeViewModel ViewModel { get; set; } 10 | 11 | public GenerateCodeDialog() 12 | { 13 | ViewModel = App.GetService(); 14 | ViewModel.IsActive = true; 15 | InitializeComponent(); 16 | } 17 | 18 | public new Task ShowAsync() => DialogHelper.SetContentDialogRoot(this).ShowAsync().AsTask(); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/DbToys.WinUI/Views/Dialogs/MysqlConnectDialog.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |