[
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [dkorecko]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\npolar: # Replace with a single Polar username\nbuy_me_a_coffee: dkorecko\nthanks_dev: # Replace with a single thanks.dev username\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**docker-compose.yaml**\n```yaml\nProvide your docker-compose.yaml file here.\n```\n\n**Logs**\nProvide logs here if applicable.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"[Feature]\"\nlabels: enhancement\nassignees: ''\n\n---\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build app\n\non:\n  pull_request:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ github.ref }}\n\n      - name: Setup .NET\n        uses: actions/setup-dotnet@v4\n        with:\n          dotnet-version: 9\n\n      - name: Restore dependencies\n        run: dotnet restore\n\n      - name: Build\n        run: dotnet build -c Release --no-restore\n\n      - name: Test\n        run: dotnet test -c Release --no-build\n"
  },
  {
    "path": ".github/workflows/docker-release.yml",
    "content": "name: Build and Publish Docker image to GHCR\n\non:\n  release:\n    types: [published]\n\njobs:\n  build-and-push:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n        with:\n          platforms: linux/amd64,linux/arm64,linux/arm/v7\n\n      - name: Log in to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ secrets.GHCR_USERNAME }}\n          password: ${{ secrets.GHCR_TOKEN }}\n\n      - name: Extract release version\n        id: vars\n        run: echo \"RELEASE_VERSION=${GITHUB_REF#refs/tags/}\" >> $GITHUB_ENV\n\n      - name: Set lowercase repository name\n        id: repo-name\n        run: echo \"REPO_LOWER=${GITHUB_REPOSITORY,,}\" >> $GITHUB_ENV\n\n      - name: Build and push Docker image\n        uses: docker/build-push-action@v5\n        with:\n          context: .\n          platforms: linux/amd64,linux/arm64,linux/arm\n          file: ./Dockerfile\n          push: true\n          tags: |\n            ghcr.io/${{ env.REPO_LOWER }}:${{ env.RELEASE_VERSION }}\n            ghcr.io/${{ env.REPO_LOWER }}:latest\n"
  },
  {
    "path": ".github/workflows/docker-unstable.yml",
    "content": "name: Build and publish unstable Docker image\n\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n    inputs:\n      branch:\n        description: \"Branch to deploy\"\n        required: true\n        default: \"main\"\n\nconcurrency:\n  group: docker-unstable-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-and-push:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.inputs.branch || github.ref }}\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n        with:\n          platforms: linux/amd64,linux/arm64,linux/arm\n\n      - name: Log in to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ secrets.GHCR_USERNAME }}\n          password: ${{ secrets.GHCR_TOKEN }}\n\n      - name: Set lowercase repository name\n        id: repo-name\n        run: echo \"REPO_LOWER=${GITHUB_REPOSITORY,,}\" >> $GITHUB_ENV\n\n      - name: Build and push Docker image\n        uses: docker/build-push-action@v6\n        with:\n          context: .\n          platforms: linux/amd64,linux/arm64,linux/arm\n          file: ./Dockerfile\n          push: true\n          tags: ghcr.io/${{ env.REPO_LOWER }}:unstable\n\n  test-multi-arch:\n    needs: build-and-push\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: read\n    strategy:\n      matrix:\n        arch: [amd64, arm64, arm]\n    steps:\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n        with:\n          platforms: linux/${{ matrix.arch }}\n\n      - name: Log in to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ secrets.GHCR_USERNAME }}\n          password: ${{ secrets.GHCR_TOKEN }}\n\n      - name: Set lowercase repository name\n        id: repo-name\n        run: echo \"REPO_LOWER=${GITHUB_REPOSITORY,,}\" >> $GITHUB_ENV\n\n      - name: Pull Docker image for ${{ matrix.arch }}\n        run: |\n          docker pull --platform linux/${{ matrix.arch }} ghcr.io/${{ env.REPO_LOWER }}:unstable\n\n      - name: Run test container for ${{ matrix.arch }}\n        run: |\n          docker run -p 8080:8080 -d --name ticky-test --platform linux/${{ matrix.arch }} ghcr.io/${{ env.REPO_LOWER }}:unstable\n          sleep 50\n          docker logs ticky-test\n          docker stop ticky-test\n          docker rm ticky-test\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Oo]ut/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n**/uploaded/**/*\n\n# Idea\n.idea/"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"kiroAgent.configureMCP\": \"Disabled\"\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Ticky\n\nThank you for considering contributing to Ticky! This document outlines the process for contributing to the project.\n\n## How Can I Contribute?\n\n### Reporting Bugs\n\nBefore creating bug reports, please check the issue tracker to see if the problem has already been reported. If it has and the issue is still open, add a comment to the existing issue instead of opening a new one (or add a reaction).\n\nWhen you are creating a bug report, please include as many details as possible:\n\n- Use a clear and descriptive title\n- Describe the exact steps to reproduce the problem\n- Describe the behavior you observed and what you expected to see\n- Include screenshots if possible\n- Include details about your environment (OS, browser, etc.)\n\n### Suggesting Enhancements\n\nEnhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include:\n\n- A clear and descriptive title\n- A detailed description of the proposed functionality\n- Any possible implementation details or ideas\n- Why this enhancement would be useful to most users\n\n### Pull Requests\n\nPlease follow these steps for submitting a pull request:\n\n1. Fork the repository\n2. Create a new branch for your feature (`git checkout -b feature/name-of-feature`)\n3. Make your changes\n4. Verify the changes\n5. Commit your changes (`git commit -m 'Add some feature'`)\n6. Push to your branch (`git push origin feature/name-of-feature`)\n7. Open a Pull Request\n\n#### Pull Request Guidelines\n\n- Update the README.md with details of changes if applicable\n- Follow the code style of the project\n- Reference any relevant issues in your PR description\n\n## Development Setup\n\n### Prerequisites\n\n- .NET 9.0 SDK\n- MySQL Server 8.0+\n- IDE (Visual Studio, VS Code, etc.)\n\n### Setup Steps\n\n1. Clone your fork of the repository\n2. Configure your database and e-mail connection in user secrets\n\n```json\n{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\",\n      \"Microsoft.EntityFrameworkCore.Database\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"ConnectionStrings\": {\n    \"Production\": \"Server=localhost;Database=ticky;Uid=ticky;Pwd={PASSWORD_HERE};\",\n    \"Development\": \"Server=localhost;Database=ticky;Uid=ticky;Pwd={PASSWORD_HERE};\"\n  },\n  \"Email\": {\n    \"Server\": \"{SMTP_HOST}\",\n    \"Port\": 465,\n    \"SenderName\": \"Ticky\",\n    \"SenderEmail\": \"{SMTP_EMAIL}\",\n    \"Account\": \"{SMTP_USERNAME}\",\n    \"Password\": \"{SMTP_PASSWORD}\",\n    \"Security\": true\n  }\n}\n```\n\n3. Start the application: `dotnet watch --project Ticky.Web/Ticky.Web.csproj`\n\n## Coding Conventions\n\n- Use the built-in code formatter\n- Follow C# naming conventions\n- Add comments for complex logic\n- Write descriptive commit messages\n\n## Documentation\n\nGood documentation is essential. Please update relevant documentation when making changes:\n\n- Update the README.md if relevant\n- Consider adding to the wiki for significant features\n\n## Questions?\n\nIf you have any questions about contributing, please open an issue with your question.\n\nThank you for contributing to Ticky!\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Declare ARGs for build platform and target architecture for clarity\nARG BUILDPLATFORM\n\nFROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base\nWORKDIR /app\nEXPOSE 8080\n\nFROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0 AS build\nARG TARGETARCH\nWORKDIR /src\n\n# Copy project files first for layer caching\nCOPY [\"Ticky.Web/Ticky.Web.csproj\", \"Ticky.Web/\"]\nCOPY [\"Ticky.Internal/Ticky.Internal.csproj\", \"Ticky.Internal/\"]\nCOPY [\"Ticky.Base/Ticky.Base.csproj\", \"Ticky.Base/\"]\n\n# Map Docker's TARGETARCH to the arch used in .NET RIDs and restore dependencies\nRUN export DOTNET_ARCH=$(case ${TARGETARCH} in \\\n\t\"amd64\") echo \"x64\" ;; \\\n\t\"arm64\") echo \"arm64\" ;; \\\n\t\"arm\") echo \"arm\" ;; \\\n\t*) echo \"Unsupported architecture: ${TARGETARCH}\"; exit 1 ;; \\\n\tesac) && \\\n\tdotnet restore \"Ticky.Web/Ticky.Web.csproj\" -r \"linux-${DOTNET_ARCH}\"\n\n# Copy the rest of the source code\nCOPY . .\n\n# Build and publish the application for the target runtime\nRUN export DOTNET_ARCH=$(case ${TARGETARCH} in \\\n\t\"amd64\") echo \"x64\" ;; \\\n\t\"arm64\") echo \"arm64\" ;; \\\n\t\"arm\") echo \"arm\" ;; \\\n\tesac) && \\\n\tdotnet publish \"Ticky.Web/Ticky.Web.csproj\" \\\n\t-c Release \\\n\t-o /app/publish \\\n\t-r \"linux-${DOTNET_ARCH}\" \\\n\t--no-restore \\\n\t--self-contained false\n\n# Final image stage\nFROM base AS final\nWORKDIR /app\nCOPY --from=build /app/publish .\nENTRYPOINT [\"dotnet\", \"Ticky.Web.dll\"]"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) [year] [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n    <img src=\"images/ticky_logo.png\" width=\"300\" title=\"Ticky logo\">\n</p>\n\n# Ticky\n\nTicky is a modern, feature-rich task management system with Kanban-style boards, built using ASP.NET Core Blazor. It is designed to help you manage your projects and tasks efficiently, whether for personal use or team collaboration. Ticky is fully open-source and free to use (and will always be), with a focus on simplicity and usability.\n\n## ❓ The why\n\nYou might be thinking, \"Another Kanban app?\" and that's fair! As someone who navigated between Trello for personal tasks and commercial projects, and Jira at work, I often found myself searching endlessly for \"power-ups\" that eventually turned into paid features, or trying open-source solutions that didn't quite hit the mark on what I needed or simply lacked the right feel. Ticky was born from that experience - a desire to build something truly comprehensive, intuitive, and always accessible. It's my answer to those frustrations, and it means Ticky will always be free and fully open-source.\n\n## 🌟 Features\n\nTicky is packed with powerful features designed to make your task management seamless and enjoyable:\n\n- **Projects**: Create and manage projects to group your boards.\n- **Boards**: Create and manage your own Kanban boards. You can even make them favorites to stay atop the list.\n- **Templates**: You can clone boards, therefore allowing you to use boards as templates.\n- **Columns**: Each board can have any amount of columns, all of which are collapsible. You can specify a max card limit, automatically mark the cards within the column as finished and automatically order them.\n- **Cards**: Create, edit, and move task cards between columns with drag-and-drop functionality. At a glance see all important information about a card. Decide where new cards are placed.\n- **Subtasks**: Break down tasks into smaller, manageable subtasks with completion tracking.\n- **Deadline Management**: Set and track deadlines with color-coded indicators.\n- **Time Tracking**: Track time spent on tasks with built-in timer functionality. Additionally view how much time has been spent on a specific column in the stats section.\n- **Labels and Priorities**: Organize tasks with custom labels and priority levels. Label colors are fully customizable.\n- **Attachments**: Upload and manage files associated with tasks.\n- **Reminders**: Set email reminders for tasks.\n- **Card Linking**: Link related cards together (Jira-like).\n- **Activity Tracking**: Monitor all changes and activities on tasks.\n- **Comments**: Leave comments on cards to discuss and provide other useful information.\n- **User Management**: You can add users on the project level or on the board level, choosing between a Member and an Admin role. Also possible to disable user signups.\n- **Admin Panel**: For creating, editing and deleting users as an admin. Mostly for when not using SMTP.\n- **Email Notifications**: Receive notifications for deadlines, and reminders.\n- **Progress**: Track your progress within a board by seeing how many tasks have already been completed.\n- **App-wide Search**: Find cards from other boards based on their unique identificator (like TEST-1), jump directly to them.\n- **Recent board**: Immediately go back to your most recent board.\n- **Auto-generated avatars** (optional): To make things more colorful.\n- **Able to do run offline**: Ability to run fully offline, disabling the avatar service, having all the files bundled on the server and not using SMTP.\n- **Dark Mode**: A sleek dark mode for less strain on your eyes.\n- **Snooze Cards**: Reduce clutter by snoozing cards that cannot be worked on just yet.\n- **Repeat Cards**: Automatically repeat cards at specified intervals, perfect for recurring tasks.\n- **Responsive Design**: Take your tasks with you, no matter whether you are at your computer or running errands with just your phone.\n- **Completion Confetti**: Feel the satisfaction of completing each task with a bunch of confetti, there to celebrate your success.\n- **Filtering**: Easily find and organize tasks based on various criteria.\n- **Trello import**: You can import your Trello boards, including the ability to map all the assigned members from your Trello board to Ticky users.\n- ... and more!\n\n## 📋 Prerequisites\n\n- **Docker** installed on your system\n  - Windows: Download and install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)\n  - macOS: Download and install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)\n  - Linux: Install Docker Engine and Docker Compose via your package manager\n- **Basic text editor** (Notepad, VS Code, etc.) to create/edit the configuration file\n- **SMTP Server** (optional) - for email notifications and password resets\n  - Gmail, Outlook, or any email provider that supports SMTP\n  - If you don't have SMTP, Ticky will work without email features\n\n## 🚀 Getting Started\n\n### Using Docker (Recommended)\n\n**Step 1: Verify Docker Installation**\nOpen a terminal/command prompt and run:\n\n```bash\ndocker --version\n```\n\nIf these commands work, you're ready to proceed!\n\n**Step 2: Create Project Directory**\nCreate a new folder for Ticky on your computer:\n\n```bash\nmkdir ticky-app\ncd ticky-app\n```\n\n**Step 3: Create Configuration File**\nCreate a new file called `docker-compose.yaml` in your project folder and copy the following content. **Important**: Replace `your-secure-password` with a strong password of your choice (use the same password in all places where it appears):\n\n```yaml\nservices:\n  ticky-app:\n    image: ghcr.io/dkorecko/ticky:latest # or pin to a specific version (like v1.0.0) for manual updates\n    container_name: ticky-app\n    ports:\n      - \"4088:8080\"\n    restart: unless-stopped\n    volumes:\n      - ./data/app/uploaded:/app/wwwroot/uploaded\n    environment:\n      - DB_HOST=ticky-db\n      - DB_NAME=ticky # Database name, can be customized\n      - DB_USERNAME=ticky # Database username, can be customized\n      - DB_PASSWORD=your-secure-password\n      #- FULLY_OFFLINE=true # Uncomment this if you want to disable the avatar service and run fully offline.\n      #- DISABLE_USER_SIGNUPS=true # Uncomment to disable user self-registration. When true, only admins can create new users via the Admin Panel.\n      - BASE_URL=http://localhost:4088 # Base URL for generating clickable links in emails (e.g., reminder emails). Change to the base URL you use to access Ticky.\n      - SMTP_ENABLED=true # Change this to false to ignore SMTP configuration and disable SMTP setup. Resetting password via typical password reset won't work (will need to be reset by an admin via the Admin Panel), as well as reminders and notifications. Can be enabled at any time.\n      - SMTP_HOST=your-smtp-host\n      - SMTP_PORT=your-smtp-port\n      - SMTP_DISPLAY_NAME=Ticky\n      - SMTP_EMAIL=your-email@example.com\n      - SMTP_USERNAME=your-smtp-username\n      - SMTP_PASSWORD=your-smtp-password\n      - SMTP_SECURITY=true\n    depends_on:\n      ticky-db:\n        condition: service_healthy\n  ticky-db:\n    image: mysql:8\n    container_name: ticky-db\n    restart: unless-stopped\n    environment:\n      MYSQL_DATABASE: ticky # This should match DB_NAME in ticky-app container\n      MYSQL_USER: ticky # This should match DB_USERNAME in ticky-app container\n      MYSQL_ROOT_PASSWORD: your-secure-password\n      MYSQL_PASSWORD: your-secure-password # This should match DB_PASSWORD\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\"]\n      timeout: 2s\n      retries: 30\n    volumes:\n      - ./data/mysql:/var/lib/mysql\n```\n\n**Step 4: Configure Email (Optional)**\nIf you want email notifications and password reset functionality:\n\n- Replace `your-smtp-host`, `your-smtp-port`, `your-email@example.com`, etc. with your actual email provider settings\n- For Gmail: Use `smtp.gmail.com`, port `587`, and create an [App Password](https://support.google.com/accounts/answer/185833)\n- If you don't want email features, change `SMTP_ENABLED=true` to `SMTP_ENABLED=false`\n\n**Step 5: Start Ticky**\nIn your terminal/command prompt, navigate to your project folder and run:\n\n```bash\ndocker compose up -d\n```\n\nThis will:\n\n- Download the necessary Docker images (this may take a few minutes the first time)\n- Create and start the Ticky application and database\n- Set up data storage folders automatically\n\n**Step 6: Access Your Ticky Instance**\n\n1. Open your web browser and go to: `http://localhost:4088`\n2. Log in with the default admin account:\n   - **Email**: `admin@ticky.com`\n   - **Password**: `abc123`\n3. You'll be prompted to change these credentials immediately for improved security\n4. After changing your password, you'll be logged out - just log back in with your new credentials\n\n**Step 7: Add Users (If SMTP Disabled)**\nIf you disabled SMTP, you'll need to create user accounts manually through the Admin Panel. If SMTP is enabled, users can register themselves.\n\n### Troubleshooting\n\n- **Port already in use**: Change `4088:8080` to `4089:8080` (or any other available port) in the docker-compose.yaml file\n- **Permission errors**: Make sure Docker Desktop is running and you have proper permissions. In Linux, sudo can be used in front of the commands.\n- **Can't access the app**: Wait a minute after starting - the database needs time to initialize on first run\n\n### Manual Setup\n\n1. Clone the repository:\n\n   ```\n   git clone https://github.com/dkorecko/Ticky.git\n   cd Ticky\n   ```\n\n2. Set up your environment variables.\n\n3. Run the application:\n   ```\n   dotnet run --project Ticky.Web/Ticky.Web.csproj\n   ```\n\n## 📷 Preview\n\n![Image of the landing page in light mode](images/landing_light.png)\n![Image of the board in light mode](images/board_light.png)\n![Image of the card in light mode](images/card_light.png)\n![Image of the landing page in dark mode](images/landing_dark.png)\n![Image of the board in dark mode](images/board_dark.png)\n![Image of the card in dark mode](images/card_dark.png)\n\n## 🤝 Community\n\nIf you have any questions, need help setting up, want to share your feedback or discuss ideas and new features, then I have created a [Discord](https://discord.gg/DHCZqYwUUb) server. I’m always eager to hear from users and improve Ticky based on your needs.\n\n## 🛠️ Project Structure\n\n- **Ticky.Base**: Core entities, models, and shared components.\n- **Ticky.Internal**: Data access, services, and business logic.\n- **Ticky.Web**: Blazor web application, UI components, and user interface.\n\n## 🔧 Configuration\n\n### Database Setup\n\nThe application automatically applies migrations on startup.\n\n## 🧪 Development\n\n### Building\n\n```\ndotnet build\n```\n\n### Running Tests\n\n```\ndotnet test\n```\n\n### Watch Mode\n\n```\ndotnet watch\n```\n\n## 🔄 CI/CD\n\nThe project includes GitHub Actions workflows for CI/CD:\n\n- Automated builds and tests on pull requests\n- Docker image publishing to GitHub Container Registry (GHCR) on releases\n\n## 📝 Contributing\n\nContributions are welcome! See the [CONTRIBUTING.md](CONTRIBUTING.md) file for details.\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 👏 Acknowledgements\n\n- [Blazor](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor) - Web framework used\n- [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) - ORM used\n- [TailwindCSS](https://tailwindcss.com/) - CSS framework\n- [Font Awesome](https://fontawesome.com/) - Icons\n- [Sortable.js](https://github.com/SortableJS/Sortable) - Drag-and-drop functionality\n\n## 📞 Contact\n\nHave questions or feedback? I'd love to hear from you! Please feel free to open an issue on this repository.\n\n---\n\nMade with ❤️\n"
  },
  {
    "path": "Ticky.Base/Constants.cs",
    "content": "namespace Ticky.Base\n{\n    public static class Constants\n    {\n        public static bool SMTP_ENABLED = true;\n        public static bool FULLY_OFFLINE;\n        public static bool DISABLE_USER_SIGNUPS = false;\n        public static string BASE_URL = string.Empty;\n#if DEBUG\n        public const string APP_NAME = \"Ticky [DEV]\";\n#else\n        public const string APP_NAME = \"Ticky\";\n#endif\n\n        public static class CascadingParameters\n        {\n            public const string CurrentAccount = \"CurrentAccount\";\n            public const string MainLayout = \"MainLayout\";\n        }\n\n        public static class Defaults\n        {\n            public const string ADMIN_EMAIL = \"admin@ticky.com\";\n            public const string ADMIN_PASSWORD = \"abc123\";\n        }\n\n        public static class Emails\n        {\n            public static readonly string BASE_PATH = Path.Combine(WWW_ROOT, \"emails\");\n\n            public static class Mappings\n            {\n                public const string VERIFICATION_CODE = \"{VERIFICATION_CODE}\";\n                public const string CARD_CODE = \"{CARD_CODE}\";\n                public const string CARD_TEXT = \"{CARD_TEXT}\";\n                public const string CARD_SCHEDULED_FOR = \"{CARD_SCHEDULED_FOR}\";\n                public const string CARD_DESCRIPTION = \"{CARD_DESCRIPTION}\";\n                public const string CARD_SUBTASKS = \"{CARD_SUBTASKS}\";\n                public const string CARD_URL = \"{CARD_URL}\";\n                public const string BASE_URL = \"{BASE_URL}\";\n                public const string CARD_DEADLINE = \"{CARD_DEADLINE}\";\n                public const string CARD_DEADLINE_SECTION = \"{CARD_DEADLINE_SECTION}\";\n                public const string CARD_DESCRIPTION_SECTION = \"{CARD_DESCRIPTION_SECTION}\";\n                public const string CARD_SUBTASKS_SECTION = \"{CARD_SUBTASKS_SECTION}\";\n                public const string SUBTASK_TEXT = \"{SUBTASK_TEXT}\";\n                public const string SUBTASK_ICON = \"{SUBTASK_ICON}\";\n                public const string SUBTASK_ICON_COLOR = \"{SUBTASK_ICON_COLOR}\";\n                public const string SUBTASK_COMPLETED_CLASS = \"{SUBTASK_COMPLETED_CLASS}\";\n            }\n        }\n\n        public static class Hubs\n        {\n            public const string UPDATE_HUB = \"/updatehub\";\n        }\n\n        public static class Limits\n        {\n            public const int MINIMUM_SECOND_HOSTED_SERVICE_DELAY = 15;\n            public const int DEFAULT_NOTIFICATION_TIME_IN_MS = 5000;\n            public const int FILE_NAME_LENGTH = 10;\n            public const long MAX_FILE_SIZE = 15360 * 1024;\n            public const long MAX_IMAGE_SIZE = MAX_FILE_SIZE;\n            public const long MAX_JSON_SIZE = MAX_FILE_SIZE;\n            public const int MAX_FILES = 20;\n            public const int DEBOUNCE_TIME_IN_MS = 1000;\n        }\n\n        public static class Mappings\n        {\n            public const string LOGIN_PATH = \"/auth/login\";\n            public const string LOGOUT_PATH = \"/auth/logout\";\n            public const string BOARD_PATH = \"/boards\";\n            public const string ATTACHMENTS_API_PATH = \"/api/attachments\";\n            public const string ATTACHMENTS_DOWNLOAD_PATH = ATTACHMENTS_API_PATH + \"/download\";\n        }\n\n        public static class Policies\n        {\n            public const string RequireAdmin = \"RequireAdmin\";\n        }\n\n        public static class Roles\n        {\n            public const string Admin = \"Admin\";\n        }\n\n        public static class StorageKeys\n        {\n            public const string BoardPreferences = \"Ticky_BoardPreferences\";\n            public const string FilterPreferencesPrefix = \"Ticky_FilterPreferences\";\n        }\n\n        public static readonly string WWW_ROOT = Path.Combine(\n            AppDomain.CurrentDomain.BaseDirectory,\n            \"wwwroot\"\n        );\n        public static readonly string INFORMATION_PATH = Path.Combine(WWW_ROOT, \"information.json\");\n        public static readonly string SAVE_UPLOADED_PATH = $\"wwwroot/uploaded\";\n        public static readonly string SAVE_UPLOADED_IMAGES_PATH = $\"{SAVE_UPLOADED_PATH}/images\";\n        public static readonly string SAVE_UPLOADED_FILES_PATH = $\"{SAVE_UPLOADED_PATH}/files\";\n        public static readonly string ACCESS_UPLOADED_PATH = $\"./uploaded\";\n        public static readonly string ACCESS_UPLOADED_IMAGES_PATH =\n            $\"{ACCESS_UPLOADED_PATH}/images\";\n        public static readonly string ACCESS_UPLOADED_FILES_PATH = $\"{ACCESS_UPLOADED_PATH}/files\";\n\n        public const string REPEATED_KEY = \"is repeated by\";\n\n        public static readonly Dictionary<string, string> LINK_TYPE_PAIRS =\n            new()\n            {\n                { \"is blocked by\", \"blocks\" },\n                { \"is tested by\", \"tests\" },\n                { \"relates to\", \"relates to\" },\n                { REPEATED_KEY, \"repeats\" }\n            };\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Converters/ColorToInt32Converter.cs",
    "content": "using Microsoft.EntityFrameworkCore.Storage.ValueConversion;\n\nnamespace Ticky.Base.Converters;\n\npublic class ColorToInt32Converter : ValueConverter<Color, int>\n{\n    public ColorToInt32Converter()\n        : base(c => c.ToArgb(), v => Color.FromArgb(v)) { }\n}\n"
  },
  {
    "path": "Ticky.Base/Converters/StringToTimeSpanConverter.cs",
    "content": "namespace Ticky.Base.Converters;\n\npublic static class StringToTimeSpanConverter\n{\n    public static TimeSpan ConvertToTimeSpan(this string str)\n    {\n        var time = new TimeSpan();\n\n        foreach (var part in str.Split(' '))\n        {\n            if (part.EndsWith(\"h\", StringComparison.OrdinalIgnoreCase))\n                time = time.Add(TimeSpan.FromHours(int.Parse(part.TrimEnd('h'))));\n            else if (part.EndsWith(\"m\", StringComparison.OrdinalIgnoreCase))\n                time = time.Add(TimeSpan.FromMinutes(int.Parse(part.TrimEnd('m'))));\n            else if (part.EndsWith(\"s\", StringComparison.OrdinalIgnoreCase))\n                time = time.Add(TimeSpan.FromSeconds(int.Parse(part.TrimEnd('s'))));\n            else\n                throw new InvalidDataException();\n        }\n\n        return time;\n    }\n\n    public static string ConvertToString(this TimeSpan time)\n    {\n        string result = string.Empty;\n\n        if (time.Hours > 0)\n            result += $\"{time.Hours}h \";\n\n        if (time.Minutes > 0)\n            result += $\"{time.Minutes}m \";\n\n        if (time.Seconds > 0 || string.IsNullOrWhiteSpace(result))\n            result += $\"{time.Seconds}s \";\n\n        return result.Trim();\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/InformationDTO.cs",
    "content": "namespace Ticky.Base.DTOs;\n\npublic class InformationDTO\n{\n    public required string Title { get; set; }\n\n    public required string Message { get; set; }\n\n    public required int Id { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Notification.cs",
    "content": "namespace Ticky.Base.DTOs;\n\npublic record Notification(string text, NotificationType type = NotificationType.Success)\n{\n    public NotificationType Type { get; set; } = type;\n    public string Text { get; set; } = text;\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloCardDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloCardDTO\n{\n    [JsonPropertyName(\"id\")]\n    public required string Id { get; set; }\n\n    [JsonPropertyName(\"name\")]\n    public required string Name { get; set; }\n\n    [JsonPropertyName(\"desc\")]\n    public required string Description { get; set; }\n\n    [JsonPropertyName(\"closed\")]\n    public required bool Closed { get; set; }\n\n    [JsonPropertyName(\"due\")]\n    public required DateTime? Due { get; set; }\n\n    [JsonPropertyName(\"idList\")]\n    public required string IdList { get; set; }\n\n    [JsonPropertyName(\"idLabels\")]\n    public required List<string> IdLabels { get; set; }\n\n    [JsonPropertyName(\"mirrorSourceId\")]\n    public required string MirrorSourceId { get; set; }\n\n    [JsonPropertyName(\"dueComplete\")]\n    public required bool DueComplete { get; set; }\n\n    [JsonPropertyName(\"dateCompleted\")]\n    public required DateTime? DateCompleted { get; set; }\n\n    [JsonPropertyName(\"dueReminder\")]\n    public required int? DueReminder { get; set; }\n\n    [JsonPropertyName(\"idMembers\")]\n    public required List<string> IdMembers { get; set; }\n\n    [JsonPropertyName(\"idMemberCreator\")]\n    public required string IdMemberCreator { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloCheckItemDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloCheckItemDTO\n{\n    [JsonPropertyName(\"id\")]\n    public required string Id { get; set; }\n\n    [JsonPropertyName(\"name\")]\n    public required string Name { get; set; }\n\n    [JsonPropertyName(\"idChecklist\")]\n    public required string IdChecklist { get; set; }\n\n    [JsonPropertyName(\"state\")]\n    public required string State { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloChecklistDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloChecklistDTO\n{\n    [JsonPropertyName(\"id\")]\n    public required string Id { get; set; }\n\n    [JsonPropertyName(\"name\")]\n    public required string Name { get; set; }\n\n    [JsonPropertyName(\"idCard\")]\n    public required string IdCard { get; set; }\n\n    [JsonPropertyName(\"checkItems\")]\n    public required List<TrelloCheckItemDTO> CheckItems { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloLabelDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello\n{\n    public class TrelloLabelDTO\n    {\n        [JsonPropertyName(\"id\")]\n        public required string Id { get; set; }\n\n        [JsonPropertyName(\"name\")]\n        public required string Name { get; set; }\n\n        [JsonPropertyName(\"color\")]\n        public required string Color { get; set; }\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloListDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloListDTO\n{\n    [JsonPropertyName(\"id\")]\n    public required string Id { get; set; }\n\n    [JsonPropertyName(\"name\")]\n    public required string Name { get; set; }\n\n    [JsonPropertyName(\"closed\")]\n    public bool Closed { get; set; }\n\n    [JsonPropertyName(\"softLimit\")]\n    public int? SoftLimit { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloMemberDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloMemberDTO\n{\n    [JsonPropertyName(\"id\")]\n    public required string Id { get; set; }\n\n    [JsonPropertyName(\"fullName\")]\n    public required string FullName { get; set; }\n\n    [JsonPropertyName(\"username\")]\n    public required string Username { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/Trello/TrelloPreferencesDTO.cs",
    "content": "namespace Ticky.Base.DTOs.Trello;\n\npublic class TrelloPreferencesDTO\n{\n    [JsonPropertyName(\"selfJoin\")]\n    public required bool SelfJoin { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/DTOs/TrelloImportDTO.cs",
    "content": "using Ticky.Base.DTOs.Trello;\n\nnamespace Ticky.Base.DTOs;\n\npublic class TrelloImportDTO\n{\n    [JsonPropertyName(\"name\")]\n    public required string Name { get; set; }\n\n    [JsonPropertyName(\"desc\")]\n    public required string Description { get; set; }\n\n    [JsonPropertyName(\"starred\")]\n    public required bool Starred { get; set; }\n\n    [JsonPropertyName(\"prefs\")]\n    public required TrelloPreferencesDTO Preferences { get; set; }\n\n    [JsonPropertyName(\"lists\")]\n    public required List<TrelloListDTO> Lists { get; set; }\n\n    [JsonPropertyName(\"cards\")]\n    public required List<TrelloCardDTO> Cards { get; set; }\n\n    [JsonPropertyName(\"checklists\")]\n    public required List<TrelloChecklistDTO> Checklists { get; set; }\n\n    [JsonPropertyName(\"labels\")]\n    public required List<TrelloLabelDTO> Labels { get; set; }\n\n    [JsonPropertyName(\"members\")]\n    public required List<TrelloMemberDTO> Members { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Abstractions/AbstractDbEntity.cs",
    "content": "namespace Ticky.Base.Entities.Abstractions;\n\npublic abstract class AbstractDbEntity : IDbEntry\n{\n    public int Id { get; set; }\n\n    public DateTime CreatedAt { get; init; } = DateTime.Now;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Abstractions/IAssignable.cs",
    "content": "namespace Ticky.Base.Entities.Abstractions;\n\npublic interface IAssignable\n{\n    public List<User> Assignees { get; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Abstractions/IDbEntry.cs",
    "content": "namespace Ticky.Base.Entities.Abstractions;\n\npublic interface IDbEntry\n{\n    public int Id { get; set; }\n\n    public DateTime CreatedAt { get; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Abstractions/IDeletable.cs",
    "content": "namespace Ticky.Base.Entities.Abstractions;\n\npublic interface IDeletable : IDbEntry\n{\n    public string Name { get; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Abstractions/IOrderable.cs",
    "content": "namespace Ticky.Base.Entities.Abstractions;\n\npublic interface IOrderable\n{\n    public int Index { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Activity.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Activity : AbstractDbEntity\n{\n    public required int UserId { get; set; }\n    public virtual User User { get; set; } = null!;\n    public required string Text { get; set; }\n    public required int CardId { get; set; }\n    public virtual Card Card { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Attachment.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Attachment : AbstractDbEntity\n{\n    public required string FileName { get; set; }\n\n    public required string OriginalName { get; set; }\n\n    public required int CardId { get; set; }\n\n    public virtual Card Card { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Board.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Board : AbstractDbEntity, IDeletable\n{\n    [Required(AllowEmptyStrings = false)]\n    public required string Name { get; set; }\n    public required string Description { get; set; }\n\n    [Required(AllowEmptyStrings = false)]\n    [MinLength(1)]\n    [MaxLength(5)]\n    [RegularExpression(\"^[A-Z]*$\", ErrorMessage = \"The code must be in upper-case.\")]\n    public required string Code { get; set; }\n    public required int ProjectId { get; set; }\n    public virtual Project Project { get; set; } = null!;\n    public virtual List<Column> Columns { get; set; } = [];\n    public virtual List<BoardMembership> Memberships { get; set; } = [];\n    public virtual List<Label> Labels { get; set; } = [];\n    public virtual List<LastVisit> LastVisits { get; set; } = [];\n    public virtual List<Favorite> Favorites { get; set; } = [];\n    public bool DisableSortingAnimations { get; set; }\n\n    public bool VerifyAccess(User user) =>\n        Memberships.Any(x => x.UserId.Equals(user.Id))\n        || Project.Memberships.Any(x => x.UserId.Equals(user.Id));\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/BoardMembership.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class BoardMembership : AbstractDbEntity\n{\n    public required int UserId { get; set; }\n    public virtual User User { get; set; } = null!;\n\n    public required int BoardId { get; set; }\n    public virtual Board Board { get; set; } = null!;\n\n    public required bool IsAdmin { get; set; }\n\n    public required DateTime AddedAt { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Card.cs",
    "content": "using Ticky.Base.Entities.Owned;\n\nnamespace Ticky.Base.Entities;\n\npublic class Card : AbstractDbEntity, IOrderable, IDeletable, IAssignable\n{\n    public required string Name { get; set; }\n    public string Description { get; set; } = string.Empty;\n    public required int Number { get; set; }\n    public required int Index { get; set; }\n    public required int ColumnId { get; set; }\n    public CardPriority Priority { get; set; } = CardPriority.Normal;\n    public DateTime? Deadline { get; set; }\n    public bool DeadlineProcessed { get; set; }\n    public bool Flagged { get; set; }\n    public required int CreatedById { get; set; }\n    public virtual User CreatedBy { get; set; } = null!;\n    public virtual Column Column { get; set; } = null!;\n    public virtual List<Comment> Comments { get; set; } = [];\n    public virtual List<User> Assignees { get; set; } = [];\n    public virtual List<Attachment> Attachments { get; set; } = [];\n    public virtual List<Activity> Activities { get; set; } = [];\n    public virtual List<Subtask> Subtasks { get; set; } = [];\n    public virtual List<Reminder> Reminders { get; set; } = [];\n    public virtual List<Label> Labels { get; set; } = [];\n    public virtual List<TimeRecord> TimeRecords { get; set; } = [];\n    public virtual List<CardLink> LinkedIssuesOne { get; set; } = [];\n    public virtual List<CardLink> LinkedIssuesTwo { get; set; } = [];\n\n    public RepeatInfo? RepeatInfo { get; set; }\n\n    public DateTime? SnoozedUntil { get; set; }\n\n    public TimeSpan GetTotalTime() =>\n        TimeRecords.Select(x => x.GetTotalTime()).Sum();\n\n    public DateTime CalculateNextRepeat(DateTime from)\n    {\n        if (RepeatInfo is null)\n            throw new Exception(\"Cannot calculate next repeat on card with no repeat.\");\n\n        var startDate = RepeatInfo.LastRepeat;\n        var finalDate = new DateTime(DateOnly.FromDateTime(startDate.Date), RepeatInfo.Time);\n\n        if (\n            (int)RepeatInfo.Type < (int)RepeatType.EveryXthDay\n            && RepeatInfo.Time < TimeOnly.FromDateTime(RepeatInfo.LastRepeat)\n        )\n        {\n            finalDate = finalDate.AddDays(1);\n        }\n\n        switch (RepeatInfo.Type)\n        {\n            case RepeatType.Daily:\n                return finalDate;\n            case RepeatType.WeekDays:\n            {\n                var allowedDaysOfWeek = RepeatInfo.Selected!.Split(',').Select(x => x).ToList();\n\n                while (!allowedDaysOfWeek.Any(x => finalDate.DayOfWeek.ToString().Contains(x)))\n                    finalDate = finalDate.AddDays(1);\n\n                return finalDate;\n            }\n            case RepeatType.MonthDayNumber:\n            {\n                var allowedDaysOfMonth = RepeatInfo.Selected!.Split(',').Select(x => x).ToList();\n\n                while (!allowedDaysOfMonth.Contains(finalDate.Day.ToString()))\n                    finalDate = finalDate.AddDays(1);\n\n                return finalDate;\n            }\n            case RepeatType.EveryXthDay:\n                return finalDate.AddDays(RepeatInfo.Number!.Value);\n            case RepeatType.EveryXthWeek:\n                return finalDate.AddDays(RepeatInfo.Number!.Value * 7);\n            case RepeatType.EveryXthMonth:\n                return finalDate.AddMonths(RepeatInfo.Number!.Value);\n            case RepeatType.EveryXthYear:\n                return finalDate.AddYears(RepeatInfo.Number!.Value);\n        }\n\n        throw new Exception(\"Unresolved repeat type.\");\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/CardLink.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class CardLink : AbstractDbEntity\n{\n    public required int CardOneId { get; set; }\n\n    public virtual Card CardOne { get; set; } = null!;\n\n    public required int CardTwoId { get; set; }\n\n    public virtual Card CardTwo { get; set; } = null!;\n\n    public required string Category { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Code.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Code : AbstractDbEntity\n{\n    public required string Value { get; set; }\n\n    public required CodePurpose CodePurpose { get; set; }\n\n    public required int UserId { get; set; }\n\n    public virtual User User { get; set; } = default!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Column.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Column : AbstractDbEntity, IOrderable, IDeletable\n{\n    public required string Name { get; set; }\n    public required int BoardId { get; set; }\n    public required int Index { get; set; }\n\n    [Display(Name = \"Max Cards (0 = unlimited)\")]\n    public int MaxCards { get; set; }\n\n    [Display(Name = \"Count cards within this column as finished\")]\n    public bool Finished { get; set; }\n    public bool Collapsed { get; set; }\n\n    [Obsolete(\"This property is deprecated and will be removed in next major release.\")]\n    [Display(Name = \"Automatic card ordering\")]\n    public OrderRule OrderRule { get; set; }\n    public virtual Board Board { get; set; } = null!;\n    public virtual List<Card> Cards { get; set; } = [];\n\n    [Display(Name = \"New card placement\")]\n    public CardPlacement NewCardPlacement { get; set; } = CardPlacement.Bottom;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Comment.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Comment : AbstractDbEntity\n{\n    public required string Text { get; set; }\n    public required int CreatedById { get; set; }\n    public virtual User CreatedBy { get; set; } = null!;\n    public required int CardId { get; set; }\n    public virtual Card Card { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Favorite.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Favorite : AbstractDbEntity\n{\n    public required int UserId { get; set; }\n\n    public virtual User User { get; set; } = null!;\n\n    public required int BoardId { get; set; }\n\n    public virtual Board Board { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Label.cs",
    "content": "namespace Ticky.Base.Entities\n{\n    public class Label : AbstractDbEntity, IDeletable\n    {\n        public required string Name { get; set; }\n\n        public required Color TextColor { get; set; }\n\n        public required Color BackgroundColor { get; set; }\n\n        public required int BoardId { get; set; }\n\n        public virtual Board Board { get; set; } = null!;\n\n        public virtual List<Card> OnCards { get; set; } = [];\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/LastVisit.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class LastVisit : AbstractDbEntity\n{\n    public required int BoardId { get; set; }\n    public virtual Board Board { get; set; } = null!;\n\n    public required DateTime VisitTime { get; set; }\n\n    public required int UserId { get; set; }\n    public virtual User User { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Owned/RepeatInfo.cs",
    "content": "namespace Ticky.Base.Entities.Owned;\n\n[Owned]\npublic class RepeatInfo\n{\n    public required RepeatType Type { get; set; }\n\n    public required TimeOnly Time { get; set; }\n\n    public int? Number { get; set; }\n\n    public string? Selected { get; set; }\n\n    public DateTime LastRepeat { get; set; } = DateTime.Now;\n\n    public required CardPlacement CardPlacement { get; set; }\n\n    public int? TargetColumnId { get; set; }\n\n    public string GetRepeatString() =>\n        Type switch\n        {\n            RepeatType.Daily => \"Daily\",\n            RepeatType.WeekDays => $\"On each {string.Join(\", \", Selected!.Split(','))}\",\n            RepeatType.MonthDayNumber\n                => $\"On day {string.Join(\", \", Selected!.Split(','))} of the month\",\n            RepeatType.EveryXthDay => $\"Every {Number} days\",\n            RepeatType.EveryXthWeek => $\"Every {Number} weeks\",\n            RepeatType.EveryXthMonth => $\"Every {Number} months\",\n            RepeatType.EveryXthYear => $\"Every {Number} years\",\n            _ => \"No repeat\"\n        };\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Project.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Project : AbstractDbEntity, IDeletable\n{\n    [Required(AllowEmptyStrings = false)]\n    public required string Name { get; set; }\n\n    public virtual List<Board> Boards { get; set; } = [];\n\n    public virtual List<ProjectMembership> Memberships { get; set; } = [];\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/ProjectMembership.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class ProjectMembership : AbstractDbEntity\n{\n    public required int UserId { get; set; }\n    public virtual User User { get; set; } = null!;\n\n    public required int ProjectId { get; set; }\n    public virtual Project Project { get; set; } = null!;\n\n    public required bool IsAdmin { get; set; }\n\n    public required DateTime AddedAt { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Reminder.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Reminder : AbstractDbEntity\n{\n    public required DateTime At { get; set; }\n    public required int CardId { get; set; }\n    public virtual Card Card { get; set; } = null!;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/Subtask.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class Subtask : AbstractDbEntity, IOrderable, IAssignable\n{\n    public required int Index { get; set; }\n    public required string Text { get; set; }\n    public bool Completed { get; set; }\n    public required int CardId { get; set; }\n    public virtual Card Card { get; set; } = null!;\n    public virtual List<User> Assignees { get; set; } = [];\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/TimeRecord.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class TimeRecord : AbstractDbEntity\n{\n    public required int CardId { get; set; }\n\n    public virtual Card Card { get; set; } = null!;\n\n    public required int UserId { get; set; }\n\n    public virtual User User { get; set; } = null!;\n\n    public required DateTime StartedAt { get; set; }\n\n    public DateTime? EndedAt { get; set; }\n\n    public TimeSpan GetTotalTime() =>\n        (EndedAt ?? DateTime.Now) - StartedAt;\n}\n"
  },
  {
    "path": "Ticky.Base/Entities/User.cs",
    "content": "namespace Ticky.Base.Entities;\n\npublic class User : IdentityUser<int>, IDbEntry, IDeletable\n{\n    [NotMapped]\n    public string Name\n    {\n        get => DisplayName;\n    }\n\n    public virtual Code? EmailVerificationCode { get; set; }\n\n    public virtual List<ProjectMembership> ProjectMemberships { get; set; } = [];\n\n    public virtual List<BoardMembership> BoardMemberships { get; set; } = [];\n\n    public virtual List<Card> CreatedCards { get; set; } = [];\n\n    public virtual List<Comment> CreatedComments { get; set; } = [];\n\n    public virtual List<Card> AssignedTo { get; set; } = [];\n\n    public virtual List<Activity> Activities { get; set; } = [];\n\n    public virtual List<TimeRecord> TimeRecords { get; set; } = [];\n\n    public virtual List<LastVisit> LastVisits { get; set; } = [];\n\n    public virtual List<Favorite> Favorites { get; set; } = [];\n\n    public virtual List<Subtask> Subtasks { get; set; } = [];\n\n    public required string DisplayName { get; set; }\n\n    public bool InstantDelete { get; set; }\n\n    public bool AutomaticCardEdit { get; set; }\n\n    public bool AutomaticDeadlineReminder { get; set; }\n\n    public bool AutomaticAssign { get; set; }\n\n    public string? ProfilePictureFileName { get; set; }\n\n    public int? LastVisitedBoardId { get; set; }\n\n    public bool NeedsNewCredentials { get; set; }\n\n    public DateTime CreatedAt { get; set; } = DateTime.Now;\n\n    public int? LastViewedInformation { get; set; }\n\n    public DateTime? InformationSnoozeUntil { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/CardPlacement.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum CardPlacement\n{\n    Top = 0,\n    Bottom = 1\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/CardPriority.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum CardPriority\n{\n    Normal,\n    Medium,\n    High,\n    Critical\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/CodePurpose.cs",
    "content": "﻿namespace Ticky.Base.Enums;\n\npublic enum CodePurpose\n{\n    NewAccount,\n    ForgottenPassword\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/DeadlineColor.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum DeadlineColor\n{\n    Default,\n    Yellow,\n    Red,\n    Green\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/ImportSource.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum ImportSource\n{\n    Trello\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/ImportType.cs",
    "content": ""
  },
  {
    "path": "Ticky.Base/Enums/NotificationType.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum NotificationType\n{\n    Success,\n    Fail\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/OperationType.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum OperationType\n{\n    [Display(Name = \"added\")]\n    Added,\n\n    [Display(Name = \"edited\")]\n    Edited,\n\n    [Display(Name = \"deleted\")]\n    Deleted,\n\n    [Display(Name = \"had their favorites status changed\")]\n    Favorited\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/OrderRule.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum OrderRule\n{\n    [Display(Name = \"No automatic ordering\")]\n    None = 0,\n\n    [Display(Name = \"By closest due date\")]\n    ClosestDueDate = 1,\n\n    [Display(Name = \"By latest due date\")]\n    LatestDueDate = 2,\n\n    [Display(Name = \"By highest priority\")]\n    HighestPriority = 3,\n\n    [Display(Name = \"By lowest priority\")]\n    LowestPriority = 4,\n\n    [Display(Name = \"By newest first\")]\n    NewestFirst = 5,\n\n    [Display(Name = \"By oldest first\")]\n    OldestFirst = 6,\n\n    [Display(Name = \"Migrated\")]\n    Migrated = -1\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/RepeatType.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum RepeatType\n{\n    [Display(Name = \"Daily\")]\n    Daily = 1,\n\n    [Display(Name = \"On specific days of the week (Monday, Tuesday, ...)\")]\n    WeekDays = 10,\n\n    [Display(Name = \"On specific days of the month (eg. 1st, 15th, ...)\")]\n    MonthDayNumber = 20,\n\n    // Make sure order is correct, all above this line handle days differently from the ones below\n    [Display(Name = \"Every x days\")]\n    EveryXthDay = 100,\n\n    [Display(Name = \"Every x weeks\")]\n    EveryXthWeek = 110,\n\n    [Display(Name = \"Every x months\")]\n    EveryXthMonth = 120,\n\n    [Display(Name = \"Every x years\")]\n    EveryXthYear = 130\n}\n"
  },
  {
    "path": "Ticky.Base/Enums/TrelloArchivedHandlingType.cs",
    "content": "namespace Ticky.Base.Enums;\n\npublic enum TrelloArchivedHandlingType\n{\n    [Display(Name = \"Do not add to the board\")]\n    DontAdd,\n\n    [Display(Name = \"Add to the board\")]\n    Add\n}\n"
  },
  {
    "path": "Ticky.Base/GlobalUsings.cs",
    "content": "global using Devity.Extensions;\nglobal using System.ComponentModel.DataAnnotations;\nglobal using System.ComponentModel.DataAnnotations.Schema;\nglobal using System.Drawing;\nglobal using System.Text.Json.Serialization;\nglobal using Microsoft.AspNetCore.Identity;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using Ticky.Base.Converters;\nglobal using Ticky.Base.DTOs;\nglobal using Ticky.Base.Entities.Abstractions;\nglobal using Ticky.Base.Enums;\nglobal using Ticky.Base.Validation;\n"
  },
  {
    "path": "Ticky.Base/Models/BoardPreferencesModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class BoardPreferencesModel\n{\n    public bool ShowStats { get; set; } = false;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/CloneBoardModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class CloneBoardModel\n{\n    [Display(Name = \"Target project\")]\n    [Required]\n    public int? TargetProjectId { get; set; }\n\n    [Display(Name = \"Board code/identifier\")]\n    [Required(AllowEmptyStrings = false)]\n    [MinLength(1)]\n    [MaxLength(5)]\n    [RegularExpression(\"^[A-Z]*$\", ErrorMessage = \"The code must be in upper-case.\")]\n    public string Code { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/CreateCardModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class CreateCardModel\n{\n    public string Text { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/CredentialsModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class CredentialsModel\n{\n    [Display(Name = \"Current e-mail address (username)\")]\n    [Required(AllowEmptyStrings = false)]\n    [EmailAddress]\n    public string OldEmailAddress { get; set; } = string.Empty;\n\n    [Display(Name = \"New e-mail address (username)\")]\n    [Required(AllowEmptyStrings = false)]\n    [EmailAddress]\n    public string NewEmailAddress { get; set; } = string.Empty;\n\n    [Display(Name = \"Current password\")]\n    [DataType(DataType.Password)]\n    public string OldPassword { get; set; } = string.Empty;\n\n    [Display(Name = \"New password\")]\n    [DataType(DataType.Password)]\n    public string NewPassword { get; set; } = string.Empty;\n\n    [Display(Name = \"Repeat new password\")]\n    [DataType(DataType.Password)]\n    [Compare(nameof(NewPassword))]\n    public string RepeatPassword { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/DeadlineModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class DeadlineModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [DataType(DataType.DateTime)]\n    public DateTime At { get; set; } = DateTime.Now;\n\n    [Required(AllowEmptyStrings = false)]\n    [RegularExpression(\n        \"^([01][0-9]|2[0-3]):[0-5][0-9]$\",\n        ErrorMessage = \"The time must be in HH:mm format.\"\n    )]\n    public string Time { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/FilterCardsModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class FilterCardsModel\n{\n    public string Text { get; set; } = string.Empty;\n\n    public HashSet<int> AssignedUserIds { get; set; } = [];\n\n    public HashSet<int> LabelIds { get; set; } = [];\n\n    public bool IncludeUnassigned { get; set; }\n\n    public bool ExcludeCompleted { get; set; }\n\n    public bool ExpandAssignedUsersSection { get; set; }\n\n    public bool ExpandLabelsSection { get; set; }\n\n    public bool IsAnyFilterApplied()\n    {\n        return !string.IsNullOrWhiteSpace(Text)\n            || AssignedUserIds.Count > 0\n            || LabelIds.Count > 0\n            || IncludeUnassigned\n            || ExcludeCompleted;\n    }\n\n    public void ClearFilters()\n    {\n        Text = string.Empty;\n        AssignedUserIds.Clear();\n        LabelIds.Clear();\n        IncludeUnassigned = false;\n        ExcludeCompleted = false;\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Models/ImportModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class ImportModel\n{\n    public ImportSource Source { get; set; } = ImportSource.Trello;\n\n    [Display(Name = \"What to do with an item that was archived\")]\n    public TrelloArchivedHandlingType ArchivedCardsHandling { get; set; } =\n        TrelloArchivedHandlingType.DontAdd;\n\n    [Required(ErrorMessage = \"There was no valid uploaded file.\")]\n    public TrelloImportDTO? ImportDto { get; set; }\n\n    [Required(AllowEmptyStrings = false)]\n    [MinLength(1)]\n    [MaxLength(5)]\n    [RegularExpression(\"^[A-Z]*$\", ErrorMessage = \"The code must be in upper-case.\")]\n    public string Code { get; set; } = string.Empty;\n\n    public string[]? MemberIdentifiers { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Models/LabelModel.cs",
    "content": "﻿namespace Ticky.Base.Models;\n\npublic class LabelModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [Display(Name = \"Label text\")]\n    public string Text { get; set; } = string.Empty;\n\n    [Required(AllowEmptyStrings = false)]\n    [Display(Name = \"Text color\")]\n    public Color? TextColor { get; set; }\n\n    [Required(AllowEmptyStrings = false)]\n    [Display(Name = \"Background color\")]\n    public Color? BackgroundColor { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Base/Models/LinkCardsModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class LinkCardsModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [Display(Name = \"Text\")]\n    public string Text { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/ReminderModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class ReminderModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [DataType(DataType.DateTime)]\n    public DateTime At { get; set; } = DateTime.Now;\n\n    [Required(AllowEmptyStrings = false)]\n    [RegularExpression(\n        \"^([01][0-9]|2[0-3]):[0-5][0-9]$\",\n        ErrorMessage = \"The time must be in HH:mm format.\"\n    )]\n    public string Time { get; set; } =\n        DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute).ToString(\"HH:mm\");\n}\n"
  },
  {
    "path": "Ticky.Base/Models/RepeatCardModel.cs",
    "content": "using System.ComponentModel;\n\nnamespace Ticky.Base.Models;\n\npublic class RepeatCardModel\n{\n    public RepeatType Type { get; set; } = RepeatType.Daily;\n\n    [Display(Name = \"Days within month (1,15,31 format)\")]\n    [RequiredIf(nameof(Type), RepeatType.MonthDayNumber)]\n    [RegularExpression(\n        \"^(3[01]|[12][0-9]|[1-9])(?:,(3[01]|[12][0-9]|[1-9]))*$\",\n        ErrorMessage = \"This field must be in this format: 1,15,31\"\n    )]\n    public string? SelectedMonthDays { get; set; }\n\n    [Display(Name = \"Days to repeat on (Mon,Tue,Wed format)\")]\n    [RequiredIf(nameof(Type), RepeatType.WeekDays)]\n    [RegularExpression(\n        \"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)(?:,(Mon|Tue|Wed|Thu|Fri|Sat|Sun))*$\",\n        ErrorMessage = \"This field must be in this format: Mon,Tue,Wed\"\n    )]\n    public string? SelectedWeekDays { get; set; }\n\n    [RequiredIf(\n        nameof(Type),\n        RepeatType.EveryXthDay,\n        RepeatType.EveryXthWeek,\n        RepeatType.EveryXthMonth,\n        RepeatType.EveryXthYear\n    )]\n    [Range(1, 999)]\n    public int? Number { get; set; }\n\n    [Display(Name = \"Start from date\")]\n    [Required(AllowEmptyStrings = false)]\n    [DataType(DataType.Date)]\n    public DateOnly StartDate { get; set; } = DateOnly.FromDateTime(DateTime.Now);\n\n    [Display(Name = \"Time of day for the repeat to occur\")]\n    [Required(AllowEmptyStrings = false)]\n    [RegularExpression(\n        \"^([01][0-9]|2[0-3]):[0-5][0-9]$\",\n        ErrorMessage = \"The time must be in HH:mm format.\"\n    )]\n    public string Time { get; set; } = string.Empty;\n\n    [Display(Name = \"Target column for the new card\")]\n    [Required]\n    public int? TargetColumnId { get; set; }\n\n    [Display(Name = \"Where in column to place the new card\")]\n    public CardPlacement CardPlacement { get; set; } = CardPlacement.Top;\n\n    public string? GetRelevantSelectedValue() =>\n        Type switch\n        {\n            RepeatType.MonthDayNumber => SelectedMonthDays,\n            RepeatType.WeekDays => SelectedWeekDays,\n            _ => null\n        };\n\n    public void SetRelevantSelectedValue(string? value)\n    {\n        switch (Type)\n        {\n            case RepeatType.MonthDayNumber:\n                SelectedMonthDays = value;\n                break;\n            case RepeatType.WeekDays:\n                SelectedWeekDays = value;\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Models/SnoozeCardModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class SnoozeCardModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [DataType(DataType.DateTime)]\n    public DateTime At { get; set; } = DateTime.Now;\n\n    [Required(AllowEmptyStrings = false)]\n    [RegularExpression(\n        \"^([01][0-9]|2[0-3]):[0-5][0-9]$\",\n        ErrorMessage = \"The time must be in HH:mm format.\"\n    )]\n    public string Time { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/SubtaskModel.cs",
    "content": "﻿namespace Ticky.Base.Models;\n\npublic class SubtaskModel\n{\n    [Required(AllowEmptyStrings = false)]\n    [Display(Name = \"Subtask text\")]\n    public string Text { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/TimeRecordModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class TimeRecordModel\n{\n    [Display(Name = \"Spent time (0h 0m 0s)\")]\n    [Required(AllowEmptyStrings = false)]\n    [IsValidTimeSpan]\n    public string Time { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Models/UserModel.cs",
    "content": "namespace Ticky.Base.Models;\n\npublic class UserModel\n{\n    [Display(Name = \"Full name\")]\n    [Required]\n    public string DisplayName { get; set; } = string.Empty;\n\n    [Display(Name = \"Email address\")]\n    [Required]\n    [EmailAddress]\n    public string Email { get; set; } = string.Empty;\n\n    [Display(Name = \"Password\")]\n    [Required]\n    [DataType(DataType.Password)]\n    public string Password { get; set; } = string.Empty;\n\n    [Display(Name = \"Repeat password\")]\n    [Required]\n    [DataType(DataType.Password)]\n    [Compare(nameof(Password))]\n    public string ConfirmPassword { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "Ticky.Base/Ticky.Base.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net9.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Devity.Extensions\" Version=\"2026.1.4.1450\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Identity.EntityFrameworkCore\" Version=\"9.0.9\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Ticky.Base/Validation/IsValidTimeSpan.cs",
    "content": "namespace Ticky.Base.Validation;\n\npublic class IsValidTimeSpan() : ValidationAttribute\n{\n    private const string ERROR_MESSAGE = \"This field must be in the 0h 0m 0s format.\";\n\n    protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)\n    {\n        var errorMessage = ErrorMessage ?? ERROR_MESSAGE;\n\n        if (value == null)\n            return ValidationResult.Success;\n\n        if (validationContext.MemberName is null)\n            throw new Exception(\"What\");\n\n        if (value is not string str)\n            return new ValidationResult(errorMessage, [validationContext.MemberName]);\n\n        try\n        {\n            str.ConvertToTimeSpan();\n        }\n        catch\n        {\n            return new ValidationResult(errorMessage, [validationContext.MemberName]);\n        }\n\n        return ValidationResult.Success;\n    }\n}\n"
  },
  {
    "path": "Ticky.Base/Validation/RequiredIf.cs",
    "content": "namespace Ticky.Base.Validation;\n\npublic class RequiredIfAttribute : ValidationAttribute\n{\n    private readonly string _propertyName;\n    private readonly object[] _allowedValues;\n\n    public RequiredIfAttribute(string propertyName, params object[] allowedValues)\n    {\n        _propertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName));\n        _allowedValues = allowedValues;\n    }\n\n    public override string FormatErrorMessage(string name)\n    {\n        var errorMessage = $\"Property {name} is required.\";\n        return ErrorMessage ?? errorMessage;\n    }\n\n    protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)\n    {\n        if (validationContext.MemberName is null)\n            throw new Exception(\"What\");\n\n        var property = validationContext.ObjectType.GetProperty(_propertyName);\n\n        if (property == null)\n        {\n            throw new NotSupportedException(\n                $\"Can't find {_propertyName} on searched type: {validationContext.ObjectType.Name}\"\n            );\n        }\n\n        var requiredIfTypeActualValue = property.GetValue(validationContext.ObjectInstance);\n\n        if (requiredIfTypeActualValue == null && _allowedValues != null)\n        {\n            return ValidationResult.Success;\n        }\n\n        if (\n            requiredIfTypeActualValue == null\n            || _allowedValues!.Any(x => requiredIfTypeActualValue.Equals(x))\n        )\n        {\n            return value == null\n                ? new ValidationResult(\n                    FormatErrorMessage(validationContext.DisplayName),\n                    [validationContext.MemberName]\n                )\n                : ValidationResult.Success;\n        }\n\n        return ValidationResult.Success;\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Data/DataContext.cs",
    "content": "using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;\nusing Microsoft.AspNetCore.Identity;\nusing Ticky.Base.Converters;\n\nnamespace Ticky.Internal.Data\n{\n    public class DataContext\n        : IdentityDbContext<User, IdentityRole<int>, int>,\n            IDataProtectionKeyContext\n    {\n        public DbSet<Code> Codes { get; set; } = default!;\n        public DbSet<Project> Projects { get; set; } = default!;\n        public DbSet<Board> Boards { get; set; } = default!;\n        public DbSet<Column> Columns { get; set; } = default!;\n        public DbSet<Card> Cards { get; set; } = default!;\n        public DbSet<Comment> Comments { get; set; } = default!;\n        public DbSet<ProjectMembership> ProjectMemberships { get; set; } = default!;\n        public DbSet<BoardMembership> BoardMemberships { get; set; } = default!;\n        public DbSet<Activity> Activities { get; set; } = default!;\n        public DbSet<Attachment> Attachments { get; set; } = default!;\n        public DbSet<Subtask> Subtasks { get; set; } = default!;\n        public DbSet<Reminder> Reminders { get; set; } = default!;\n        public DbSet<Label> Labels { get; set; } = default!;\n        public DbSet<TimeRecord> TimeRecords { get; set; } = default!;\n        public DbSet<LastVisit> LastVisits { get; set; } = default!;\n        public DbSet<CardLink> CardLinks { get; set; } = default!;\n        public DbSet<Favorite> Favorites { get; set; } = default!;\n        public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = default!;\n\n        public DataContext(DbContextOptions<DataContext> options)\n            : base(options) { }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            base.OnModelCreating(modelBuilder);\n\n            modelBuilder\n                .Entity<User>()\n                .HasOne(x => x.EmailVerificationCode)\n                .WithOne(x => x.User)\n                .HasForeignKey<Code>(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Project>()\n                .HasMany(x => x.Boards)\n                .WithOne(x => x.Project)\n                .HasForeignKey(x => x.ProjectId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Board>()\n                .HasMany(x => x.Columns)\n                .WithOne(x => x.Board)\n                .HasForeignKey(x => x.BoardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Column>()\n                .HasMany(x => x.Cards)\n                .WithOne(x => x.Column)\n                .HasForeignKey(x => x.ColumnId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.ProjectMemberships)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Project>()\n                .HasMany(x => x.Memberships)\n                .WithOne(x => x.Project)\n                .HasForeignKey(x => x.ProjectId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.BoardMemberships)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Board>()\n                .HasMany(x => x.Memberships)\n                .WithOne(x => x.Board)\n                .HasForeignKey(x => x.BoardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasOne(x => x.CreatedBy)\n                .WithMany(x => x.CreatedCards)\n                .HasForeignKey(x => x.CreatedById)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.CreatedComments)\n                .WithOne(x => x.CreatedBy)\n                .HasForeignKey(x => x.CreatedById)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.Comments)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder.Entity<Card>().HasMany(x => x.Assignees).WithMany(x => x.AssignedTo);\n\n            modelBuilder.Entity<Subtask>().HasMany(x => x.Assignees).WithMany(x => x.Subtasks);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.Attachments)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.Activities)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.Activities)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.Subtasks)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.Reminders)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Board>()\n                .HasMany(x => x.Labels)\n                .WithOne(x => x.Board)\n                .HasForeignKey(x => x.BoardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder.Entity<Card>().HasMany(x => x.Labels).WithMany(x => x.OnCards);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.TimeRecords)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.TimeRecords)\n                .WithOne(x => x.Card)\n                .HasForeignKey(x => x.CardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.LastVisits)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Board>()\n                .HasMany(x => x.LastVisits)\n                .WithOne(x => x.Board)\n                .HasForeignKey(x => x.BoardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.LinkedIssuesOne)\n                .WithOne(x => x.CardOne)\n                .HasForeignKey(x => x.CardOneId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Card>()\n                .HasMany(x => x.LinkedIssuesTwo)\n                .WithOne(x => x.CardTwo)\n                .HasForeignKey(x => x.CardTwoId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<Label>()\n                .Property(x => x.BackgroundColor)\n                .HasConversion<ColorToInt32Converter>();\n\n            modelBuilder\n                .Entity<Label>()\n                .Property(x => x.TextColor)\n                .HasConversion<ColorToInt32Converter>();\n\n            modelBuilder\n                .Entity<Board>()\n                .HasMany(x => x.Favorites)\n                .WithOne(x => x.Board)\n                .HasForeignKey(x => x.BoardId)\n                .OnDelete(DeleteBehavior.Cascade);\n\n            modelBuilder\n                .Entity<User>()\n                .HasMany(x => x.Favorites)\n                .WithOne(x => x.User)\n                .HasForeignKey(x => x.UserId)\n                .OnDelete(DeleteBehavior.Cascade);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Data/DataMigrator.cs",
    "content": "namespace Ticky.Internal.Data;\n\npublic class DataMigrator\n{\n    public static async Task Seed(IServiceProvider serviceProvider)\n    {\n        var dataContext = serviceProvider.GetRequiredService<DataContext>();\n\n        var topRules = new HashSet<OrderRule>\n        {\n            OrderRule.ClosestDueDate,\n            OrderRule.HighestPriority,\n            OrderRule.NewestFirst\n        };\n\n        await dataContext\n            .Columns.Where(c => c.OrderRule != OrderRule.Migrated && topRules.Contains(c.OrderRule))\n            .ExecuteUpdateAsync(s =>\n                s.SetProperty(c => c.NewCardPlacement, CardPlacement.Top)\n                    .SetProperty(c => c.OrderRule, OrderRule.Migrated)\n            );\n\n        await dataContext\n            .Columns.Where(c =>\n                c.OrderRule != OrderRule.Migrated && !topRules.Contains(c.OrderRule)\n            )\n            .ExecuteUpdateAsync(s =>\n                s.SetProperty(c => c.NewCardPlacement, CardPlacement.Bottom)\n                    .SetProperty(c => c.OrderRule, OrderRule.Migrated)\n            );\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Data/DataSeeder.cs",
    "content": "using System.Drawing;\nusing System.Security.Claims;\nusing Microsoft.AspNetCore.Identity;\n\nnamespace Ticky.Internal.Data;\n\npublic class DataSeeder\n{\n    public static async Task Seed(IServiceProvider serviceProvider)\n    {\n        var userManager = serviceProvider.GetRequiredService<UserManager<User>>();\n        var dataContext = serviceProvider.GetRequiredService<DataContext>();\n        var avatarService = serviceProvider.GetRequiredService<AvatarService>();\n\n        var adminClaim = new Claim(ClaimTypes.Role, Constants.Roles.Admin);\n        var adminUsers = await userManager.GetUsersForClaimAsync(adminClaim);\n\n        if (!adminUsers.Any())\n        {\n            var adminUser = new User\n            {\n                DisplayName = \"Default Admin\",\n                UserName = Constants.Defaults.ADMIN_EMAIL,\n                Email = Constants.Defaults.ADMIN_EMAIL,\n                EmailConfirmed = true,\n                NeedsNewCredentials = true\n            };\n\n            adminUser.ProfilePictureFileName = await avatarService.FetchAvatarAsync(\n                adminUser.DisplayName\n            );\n\n            var result = await userManager.CreateAsync(\n                adminUser,\n                Constants.Defaults.ADMIN_PASSWORD\n            );\n\n            if (!result.Succeeded)\n                throw new Exception(\n                    $\"Failed to create admin account. Errors:\\n- {string.Join(\"\\n- \", result.Errors)}\"\n                );\n\n            result = await userManager.AddClaimAsync(adminUser, adminClaim);\n\n            if (!result.Succeeded)\n                throw new Exception(\n                    $\"Failed to add claims to the admin account. Errors:\\n- {string.Join(\"\\n- \", result.Errors)}\"\n                );\n        }\n\n        if (await dataContext.Users.AnyAsync())\n            return;\n\n#if DEBUG\n        var testUser = new User\n        {\n            DisplayName = \"Testing User\",\n            UserName = \"user@ticky.com\",\n            Email = \"user@ticky.com\",\n            EmailConfirmed = true,\n            AutomaticDeadlineReminder = true\n        };\n\n        testUser.ProfilePictureFileName = await avatarService.FetchAvatarAsync(\n            testUser.DisplayName\n        );\n\n        await userManager.CreateAsync(testUser, \"abc123\");\n\n        var testProject = new Project { Name = \"DAZN\" };\n\n        var projectMembership = new ProjectMembership\n        {\n            IsAdmin = true,\n            ProjectId = testProject.Id,\n            UserId = testUser.Id,\n            AddedAt = DateTime.Now\n        };\n\n        testProject.Memberships.Add(projectMembership);\n\n        var testBoard = new Board\n        {\n            ProjectId = testProject.Id,\n            Code = \"TB\",\n            Name = \"Testing board\",\n            Description = \"This is an example of a testing board with a description.\"\n        };\n\n        testProject.Boards.Add(testBoard);\n\n        var label = new Label\n        {\n            Name = \"Important\",\n            BoardId = testBoard.Id,\n            BackgroundColor = Color.FromArgb(255, 251, 207, 232),\n            TextColor = Color.FromArgb(255, 157, 23, 77)\n        };\n\n        testBoard.Labels = [label];\n\n        var boardMembership = new BoardMembership\n        {\n            IsAdmin = true,\n            BoardId = testBoard.Id,\n            UserId = testUser.Id,\n            AddedAt = DateTime.Now\n        };\n\n        var readyColumn = new Column\n        {\n            BoardId = testBoard.Id,\n            Name = \"Ready\",\n            Index = 0\n        };\n\n        var inProgressColumn = new Column\n        {\n            BoardId = testBoard.Id,\n            Name = \"WIP\",\n            Index = 1,\n            MaxCards = 1\n        };\n\n        var doneColumn = new Column\n        {\n            BoardId = testBoard.Id,\n            Name = \"Done\",\n            Index = 2,\n            Finished = true\n        };\n\n        testBoard.Columns.Add(readyColumn);\n        testBoard.Columns.Add(inProgressColumn);\n        testBoard.Columns.Add(doneColumn);\n\n        var testCard = new Card\n        {\n            Name =\n                \"This is a pretty long example task, just trying out the word wrapping and stuff.\",\n            Description = \"AC:\",\n            Number = 1,\n            Index = 0,\n            CreatedAt = DateTime.Now,\n            Deadline = DateTime.Today.AddDays(5),\n            ColumnId = readyColumn.Id,\n            CreatedById = testUser.Id\n        };\n\n        readyColumn.Cards.Add(testCard);\n\n        testCard.Labels.Add(label);\n\n        testCard.Assignees = new List<User> { testUser };\n\n        var subtask1 = new Subtask\n        {\n            CardId = testCard.Id,\n            Index = 0,\n            Text = \"This is the first sub-task\",\n            Completed = true\n        };\n\n        var subtask2 = new Subtask\n        {\n            CardId = testCard.Id,\n            Index = 1,\n            Text = \"This is the second sub-task\",\n            Completed = true\n        };\n\n        var subtask3 = new Subtask\n        {\n            CardId = testCard.Id,\n            Index = 1,\n            Text = \"This is the third sub-task\"\n        };\n\n        testCard.Subtasks = new List<Subtask> { subtask1, subtask2, subtask3 };\n\n        var timeRecord = new TimeRecord\n        {\n            CardId = testCard.Id,\n            UserId = testUser.Id,\n            StartedAt = DateTime.Now.AddHours(-1).AddMinutes(-19),\n            EndedAt = DateTime.Now\n        };\n\n        testCard.TimeRecords.Add(timeRecord);\n\n        dataContext.Projects.Add(testProject);\n\n        await dataContext.SaveChangesAsync();\n#endif\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/GlobalUsings.cs",
    "content": "global using Devity.Extensions;\nglobal using Microsoft.AspNetCore.Identity.EntityFrameworkCore;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using Microsoft.Extensions.DependencyInjection;\nglobal using Microsoft.Extensions.Logging;\nglobal using Ticky.Base;\nglobal using Ticky.Base.DTOs;\nglobal using Ticky.Base.Entities;\nglobal using Ticky.Base.Entities.Abstractions;\nglobal using Ticky.Base.Enums;\nglobal using Ticky.Internal.Data;\nglobal using Ticky.Internal.Helpers;\nglobal using Ticky.Internal.Services;\n"
  },
  {
    "path": "Ticky.Internal/Helpers/AttachmentHelper.cs",
    "content": "﻿namespace Ticky.Internal.Helpers;\n\npublic static class AttachmentHelper\n{\n    public static string GetFileTypeFromAttachment(Attachment attachment)\n    {\n        if (attachment.OriginalName.Contains(\".doc\"))\n            return \"DOC\";\n        else if (\n            attachment.OriginalName.Contains(\".jpg\") || attachment.OriginalName.Contains(\".png\")\n        )\n            return \"Image\";\n        else if (attachment.OriginalName.Contains(\".pdf\"))\n            return \"PDF\";\n        else if (attachment.OriginalName.Contains(\".ppt\"))\n            return \"PowerPoint\";\n        else if (attachment.OriginalName.Contains(\".sql\"))\n            return \"Script\";\n        else if (attachment.OriginalName.Contains(\".txt\"))\n            return \"Text\";\n        else if (attachment.OriginalName.Contains(\".xls\"))\n            return \"Excel\";\n        else if (attachment.OriginalName.Contains(\".xml\"))\n            return \"XML\";\n        else if (attachment.OriginalName.Contains(\".zip\"))\n            return \"Archive\";\n\n        return \"Other\";\n    }\n\n    public static string GetImageNameFromAttachment(Attachment attachment)\n    {\n        if (attachment.OriginalName.Contains(\".doc\"))\n            return \"doc.png\";\n        else if (attachment.OriginalName.Contains(\".jpg\"))\n            return \"jpg.png\";\n        else if (attachment.OriginalName.Contains(\".png\"))\n            return \"png.png\";\n        else if (attachment.OriginalName.Contains(\".pdf\"))\n            return \"pdf.png\";\n        else if (attachment.OriginalName.Contains(\".ppt\"))\n            return \"ppt.png\";\n        else if (attachment.OriginalName.Contains(\".sql\"))\n            return \"sql.png\";\n        else if (attachment.OriginalName.Contains(\".txt\"))\n            return \"txt.png\";\n        else if (attachment.OriginalName.Contains(\".xls\"))\n            return \"xls.png\";\n        else if (attachment.OriginalName.Contains(\".xml\"))\n            return \"xml.png\";\n        else if (attachment.OriginalName.Contains(\".zip\"))\n            return \"zip.png\";\n\n        return \"txt.png\";\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Helpers/IndexHelper.cs",
    "content": "namespace Ticky.Internal.Helpers;\n\npublic static class IndexHelper\n{\n    public static int GetNextIndex<T>(this List<T> current)\n        where T : IOrderable\n    {\n        var result = current.Max(x => (int?)x.Index);\n\n        if (result is null)\n            return 0;\n\n        return (int)result + 1;\n    }\n\n    public static void FixIndices<T>(this List<T> current)\n        where T : IOrderable, IDbEntry\n    {\n        var orderedElements = current.OrderBy(x => x.Index).ThenBy(x => x.Id).ToList();\n\n        for (int i = 0; i < orderedElements.Count; i++)\n            orderedElements[i].Index = i;\n    }\n\n    public static void ChangeOrderOfItem<T>(this List<T> current, int currentIndex, int newIndex)\n        where T : IOrderable\n    {\n        if (currentIndex == newIndex)\n            return;\n\n        var orderedElements = current.OrderBy(x => x.Index).ToList();\n        var targetElement = orderedElements.ElementAt(currentIndex);\n\n        orderedElements.RemoveAt(currentIndex);\n        orderedElements.Insert(newIndex, targetElement);\n\n        for (int i = 0; i < orderedElements.Count; i++)\n        {\n            orderedElements.ElementAt(i).Index = i;\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Helpers/StringHelper.cs",
    "content": "using System.Text;\n\nnamespace Ticky.Internal.Helpers;\n\npublic static class StringHelper\n{\n    public static string ToFriendlyName(this string str)\n    {\n        var sb = new StringBuilder();\n\n        for (int i = 0; i < str.Length; i++)\n        {\n            if (i != 0 && char.IsUpper(str[i]))\n            {\n                sb.Append(' ');\n                sb.Append(char.ToLower(str[i]));\n            }\n            else\n                sb.Append(str[i]);\n        }\n\n        return sb.ToString();\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Helpers/TimeHelper.cs",
    "content": "namespace Ticky.Internal.Helpers;\n\npublic static class TimeHelper\n{\n    public static string ToElapsedString(this DateTime dateTime)\n    {\n        var difference = DateTime.Now - dateTime;\n\n        if (difference.TotalMinutes < 1)\n            return \"now\";\n        else if (difference.TotalMinutes < 2)\n            return $\"{Math.Round(difference.TotalMinutes)} min ago\";\n        else if (difference.TotalHours < 1)\n            return $\"{Math.Round(difference.TotalMinutes)} mins ago\";\n        else if (difference.TotalHours < 2)\n            return $\"{Math.Round(difference.TotalHours)} hr ago\";\n        else if (difference.TotalDays < 1)\n            return $\"{Math.Round(difference.TotalHours)} hrs ago\";\n        else if (difference.TotalDays <= 2)\n            return $\"yesterday, {dateTime.ToString(\"HH:mm\")}\";\n        else if (difference.TotalDays < 7)\n            return $\"{Math.Round(difference.TotalDays)} days ago\";\n        else if (dateTime.Year == DateTime.Now.Year)\n            return dateTime.ToString(\"dd. MMM\");\n\n        return dateTime.ToString(\"dd. MMM yyyy\");\n    }\n\n    public static string ToElapsedString(this TimeSpan timeSpan, bool cutOffSeconds = false)\n    {\n        string result = string.Empty;\n\n        var hoursValue = Math.Floor(timeSpan.TotalHours);\n        if (hoursValue != 0)\n            result += $\" {hoursValue}h\";\n\n        if (timeSpan.Minutes != 0)\n            result += $\" {timeSpan.Minutes}m\";\n\n        if (!cutOffSeconds)\n            result += $\" {timeSpan.Seconds}s\";\n\n        return result.Trim();\n    }\n\n    public static string ToShortString(this DateTime dateTime) =>\n        dateTime.Date == DateTime.Now.Date\n            ? dateTime.ToString(\"HH:mm\")\n            : dateTime.ToString(\"MMM d\");\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250523175138_Initial.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250523175138_Initial\")]\n    partial class Initial\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"7.0.20\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"IsFavorite\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250523175138_Initial.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class Initial : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AlterDatabase()\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetRoles\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Name = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    NormalizedName = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ConcurrencyStamp = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\")\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetRoles\", x => x.Id);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetUsers\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    DisplayName = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    InstantDelete = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    AutomaticCardEdit = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    AutomaticDeadlineReminder = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    ProfilePictureFileName = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    LastVisitedBoardId = table.Column<int>(type: \"int\", nullable: true),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    UserName = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    NormalizedUserName = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Email = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    NormalizedEmail = table.Column<string>(type: \"varchar(256)\", maxLength: 256, nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    EmailConfirmed = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    PasswordHash = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    SecurityStamp = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ConcurrencyStamp = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    PhoneNumber = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    PhoneNumberConfirmed = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    TwoFactorEnabled = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    LockoutEnd = table.Column<DateTimeOffset>(type: \"datetime(6)\", nullable: true),\n                    LockoutEnabled = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    AccessFailedCount = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetUsers\", x => x.Id);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"DataProtectionKeys\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    FriendlyName = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Xml = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\")\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_DataProtectionKeys\", x => x.Id);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Projects\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Name = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Projects\", x => x.Id);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetRoleClaims\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    RoleId = table.Column<int>(type: \"int\", nullable: false),\n                    ClaimType = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ClaimValue = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\")\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetRoleClaims\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_AspNetRoleClaims_AspNetRoles_RoleId\",\n                        column: x => x.RoleId,\n                        principalTable: \"AspNetRoles\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetUserClaims\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    ClaimType = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ClaimValue = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\")\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetUserClaims\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_AspNetUserClaims_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetUserLogins\",\n                columns: table => new\n                {\n                    LoginProvider = table.Column<string>(type: \"varchar(255)\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ProviderKey = table.Column<string>(type: \"varchar(255)\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ProviderDisplayName = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    UserId = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetUserLogins\", x => new { x.LoginProvider, x.ProviderKey });\n                    table.ForeignKey(\n                        name: \"FK_AspNetUserLogins_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetUserRoles\",\n                columns: table => new\n                {\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    RoleId = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetUserRoles\", x => new { x.UserId, x.RoleId });\n                    table.ForeignKey(\n                        name: \"FK_AspNetUserRoles_AspNetRoles_RoleId\",\n                        column: x => x.RoleId,\n                        principalTable: \"AspNetRoles\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_AspNetUserRoles_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"AspNetUserTokens\",\n                columns: table => new\n                {\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    LoginProvider = table.Column<string>(type: \"varchar(255)\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Name = table.Column<string>(type: \"varchar(255)\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Value = table.Column<string>(type: \"longtext\", nullable: true)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\")\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_AspNetUserTokens\", x => new { x.UserId, x.LoginProvider, x.Name });\n                    table.ForeignKey(\n                        name: \"FK_AspNetUserTokens_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Codes\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Value = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    CodePurpose = table.Column<int>(type: \"int\", nullable: false),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Codes\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Codes_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Boards\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Name = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Description = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Code = table.Column<string>(type: \"varchar(5)\", maxLength: 5, nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    ProjectId = table.Column<int>(type: \"int\", nullable: false),\n                    IsFavorite = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Boards\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Boards_Projects_ProjectId\",\n                        column: x => x.ProjectId,\n                        principalTable: \"Projects\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"ProjectMemberships\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    ProjectId = table.Column<int>(type: \"int\", nullable: false),\n                    IsAdmin = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    AddedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_ProjectMemberships\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_ProjectMemberships_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_ProjectMemberships_Projects_ProjectId\",\n                        column: x => x.ProjectId,\n                        principalTable: \"Projects\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"BoardMemberships\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    BoardId = table.Column<int>(type: \"int\", nullable: false),\n                    IsAdmin = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    AddedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_BoardMemberships\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_BoardMemberships_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_BoardMemberships_Boards_BoardId\",\n                        column: x => x.BoardId,\n                        principalTable: \"Boards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Columns\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Name = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    BoardId = table.Column<int>(type: \"int\", nullable: false),\n                    Index = table.Column<int>(type: \"int\", nullable: false),\n                    MaxCards = table.Column<int>(type: \"int\", nullable: false),\n                    Finished = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    Collapsed = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    OrderRule = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Columns\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Columns_Boards_BoardId\",\n                        column: x => x.BoardId,\n                        principalTable: \"Boards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Labels\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Text = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    TextColor = table.Column<int>(type: \"int\", nullable: false),\n                    BackgroundColor = table.Column<int>(type: \"int\", nullable: false),\n                    BoardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Labels\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Labels_Boards_BoardId\",\n                        column: x => x.BoardId,\n                        principalTable: \"Boards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"LastVisits\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    BoardId = table.Column<int>(type: \"int\", nullable: false),\n                    VisitTime = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_LastVisits\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_LastVisits_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_LastVisits_Boards_BoardId\",\n                        column: x => x.BoardId,\n                        principalTable: \"Boards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Cards\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Text = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Description = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Number = table.Column<int>(type: \"int\", nullable: false),\n                    Index = table.Column<int>(type: \"int\", nullable: false),\n                    ColumnId = table.Column<int>(type: \"int\", nullable: false),\n                    Priority = table.Column<int>(type: \"int\", nullable: false),\n                    Deadline = table.Column<DateTime>(type: \"datetime(6)\", nullable: true),\n                    DeadlineProcessed = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    Blocked = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    CreatedById = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Cards\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Cards_AspNetUsers_CreatedById\",\n                        column: x => x.CreatedById,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_Cards_Columns_ColumnId\",\n                        column: x => x.ColumnId,\n                        principalTable: \"Columns\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Activities\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    Text = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    At = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Activities\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Activities_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_Activities_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Attachments\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    FileName = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    OriginalName = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Attachments\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Attachments_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"CardLabel\",\n                columns: table => new\n                {\n                    LabelsId = table.Column<int>(type: \"int\", nullable: false),\n                    OnCardsId = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_CardLabel\", x => new { x.LabelsId, x.OnCardsId });\n                    table.ForeignKey(\n                        name: \"FK_CardLabel_Cards_OnCardsId\",\n                        column: x => x.OnCardsId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_CardLabel_Labels_LabelsId\",\n                        column: x => x.LabelsId,\n                        principalTable: \"Labels\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"CardLinks\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    CardOneId = table.Column<int>(type: \"int\", nullable: false),\n                    CardTwoId = table.Column<int>(type: \"int\", nullable: false),\n                    Category = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_CardLinks\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_CardLinks_Cards_CardOneId\",\n                        column: x => x.CardOneId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_CardLinks_Cards_CardTwoId\",\n                        column: x => x.CardTwoId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"CardUser\",\n                columns: table => new\n                {\n                    AssignedToId = table.Column<int>(type: \"int\", nullable: false),\n                    AssigneesId = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_CardUser\", x => new { x.AssignedToId, x.AssigneesId });\n                    table.ForeignKey(\n                        name: \"FK_CardUser_AspNetUsers_AssigneesId\",\n                        column: x => x.AssigneesId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_CardUser_Cards_AssignedToId\",\n                        column: x => x.AssignedToId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Comments\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Text = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    CreatedById = table.Column<int>(type: \"int\", nullable: false),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Comments\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Comments_AspNetUsers_CreatedById\",\n                        column: x => x.CreatedById,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_Comments_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Reminders\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    At = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Reminders\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Reminders_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"Subtasks\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    Index = table.Column<int>(type: \"int\", nullable: false),\n                    Text = table.Column<string>(type: \"longtext\", nullable: false)\n                        .Annotation(\"MySql:CharSet\", \"utf8mb4\"),\n                    Completed = table.Column<bool>(type: \"tinyint(1)\", nullable: false),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Subtasks\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Subtasks_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateTable(\n                name: \"TimeRecords\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    CardId = table.Column<int>(type: \"int\", nullable: false),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    StartedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false),\n                    EndedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: true),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_TimeRecords\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_TimeRecords_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_TimeRecords_Cards_CardId\",\n                        column: x => x.CardId,\n                        principalTable: \"Cards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Activities_CardId\",\n                table: \"Activities\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Activities_UserId\",\n                table: \"Activities\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_AspNetRoleClaims_RoleId\",\n                table: \"AspNetRoleClaims\",\n                column: \"RoleId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"RoleNameIndex\",\n                table: \"AspNetRoles\",\n                column: \"NormalizedName\",\n                unique: true);\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_AspNetUserClaims_UserId\",\n                table: \"AspNetUserClaims\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_AspNetUserLogins_UserId\",\n                table: \"AspNetUserLogins\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_AspNetUserRoles_RoleId\",\n                table: \"AspNetUserRoles\",\n                column: \"RoleId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"EmailIndex\",\n                table: \"AspNetUsers\",\n                column: \"NormalizedEmail\");\n\n            migrationBuilder.CreateIndex(\n                name: \"UserNameIndex\",\n                table: \"AspNetUsers\",\n                column: \"NormalizedUserName\",\n                unique: true);\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Attachments_CardId\",\n                table: \"Attachments\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_BoardMemberships_BoardId\",\n                table: \"BoardMemberships\",\n                column: \"BoardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_BoardMemberships_UserId\",\n                table: \"BoardMemberships\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Boards_ProjectId\",\n                table: \"Boards\",\n                column: \"ProjectId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_CardLabel_OnCardsId\",\n                table: \"CardLabel\",\n                column: \"OnCardsId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_CardLinks_CardOneId\",\n                table: \"CardLinks\",\n                column: \"CardOneId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_CardLinks_CardTwoId\",\n                table: \"CardLinks\",\n                column: \"CardTwoId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Cards_ColumnId\",\n                table: \"Cards\",\n                column: \"ColumnId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Cards_CreatedById\",\n                table: \"Cards\",\n                column: \"CreatedById\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_CardUser_AssigneesId\",\n                table: \"CardUser\",\n                column: \"AssigneesId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Codes_UserId\",\n                table: \"Codes\",\n                column: \"UserId\",\n                unique: true);\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Columns_BoardId\",\n                table: \"Columns\",\n                column: \"BoardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Comments_CardId\",\n                table: \"Comments\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Comments_CreatedById\",\n                table: \"Comments\",\n                column: \"CreatedById\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Labels_BoardId\",\n                table: \"Labels\",\n                column: \"BoardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_LastVisits_BoardId\",\n                table: \"LastVisits\",\n                column: \"BoardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_LastVisits_UserId\",\n                table: \"LastVisits\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_ProjectMemberships_ProjectId\",\n                table: \"ProjectMemberships\",\n                column: \"ProjectId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_ProjectMemberships_UserId\",\n                table: \"ProjectMemberships\",\n                column: \"UserId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Reminders_CardId\",\n                table: \"Reminders\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Subtasks_CardId\",\n                table: \"Subtasks\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_TimeRecords_CardId\",\n                table: \"TimeRecords\",\n                column: \"CardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_TimeRecords_UserId\",\n                table: \"TimeRecords\",\n                column: \"UserId\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"Activities\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetRoleClaims\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetUserClaims\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetUserLogins\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetUserRoles\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetUserTokens\");\n\n            migrationBuilder.DropTable(\n                name: \"Attachments\");\n\n            migrationBuilder.DropTable(\n                name: \"BoardMemberships\");\n\n            migrationBuilder.DropTable(\n                name: \"CardLabel\");\n\n            migrationBuilder.DropTable(\n                name: \"CardLinks\");\n\n            migrationBuilder.DropTable(\n                name: \"CardUser\");\n\n            migrationBuilder.DropTable(\n                name: \"Codes\");\n\n            migrationBuilder.DropTable(\n                name: \"Comments\");\n\n            migrationBuilder.DropTable(\n                name: \"DataProtectionKeys\");\n\n            migrationBuilder.DropTable(\n                name: \"LastVisits\");\n\n            migrationBuilder.DropTable(\n                name: \"ProjectMemberships\");\n\n            migrationBuilder.DropTable(\n                name: \"Reminders\");\n\n            migrationBuilder.DropTable(\n                name: \"Subtasks\");\n\n            migrationBuilder.DropTable(\n                name: \"TimeRecords\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetRoles\");\n\n            migrationBuilder.DropTable(\n                name: \"Labels\");\n\n            migrationBuilder.DropTable(\n                name: \"Cards\");\n\n            migrationBuilder.DropTable(\n                name: \"AspNetUsers\");\n\n            migrationBuilder.DropTable(\n                name: \"Columns\");\n\n            migrationBuilder.DropTable(\n                name: \"Boards\");\n\n            migrationBuilder.DropTable(\n                name: \"Projects\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250527093505_Favorites.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250527093505_Favorites\")]\n    partial class Favorites\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250527093505_Favorites.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class Favorites : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"IsFavorite\",\n                table: \"Boards\");\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"TimeRecords\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Subtasks\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Reminders\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Projects\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"ProjectMemberships\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"LastVisits\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Labels\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"DataProtectionKeys\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Comments\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Columns\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Codes\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"CardLinks\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Boards\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"BoardMemberships\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Attachments\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetUsers\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetUserClaims\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetRoles\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetRoleClaims\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Activities\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.CreateTable(\n                name: \"Favorites\",\n                columns: table => new\n                {\n                    Id = table.Column<int>(type: \"int\", nullable: false)\n                        .Annotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn),\n                    UserId = table.Column<int>(type: \"int\", nullable: false),\n                    BoardId = table.Column<int>(type: \"int\", nullable: false),\n                    CreatedAt = table.Column<DateTime>(type: \"datetime(6)\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Favorites\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_Favorites_AspNetUsers_UserId\",\n                        column: x => x.UserId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_Favorites_Boards_BoardId\",\n                        column: x => x.BoardId,\n                        principalTable: \"Boards\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Favorites_BoardId\",\n                table: \"Favorites\",\n                column: \"BoardId\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_Favorites_UserId\",\n                table: \"Favorites\",\n                column: \"UserId\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"Favorites\");\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"TimeRecords\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Subtasks\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Reminders\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Projects\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"ProjectMemberships\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"LastVisits\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Labels\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"DataProtectionKeys\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Comments\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Columns\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Codes\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"CardLinks\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Boards\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AddColumn<bool>(\n                name: \"IsFavorite\",\n                table: \"Boards\",\n                type: \"tinyint(1)\",\n                nullable: false,\n                defaultValue: false);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"BoardMemberships\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Attachments\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetUsers\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetUserClaims\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetRoles\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"AspNetRoleClaims\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n\n            migrationBuilder.AlterColumn<int>(\n                name: \"Id\",\n                table: \"Activities\",\n                type: \"int\",\n                nullable: false,\n                oldClrType: typeof(int),\n                oldType: \"int\")\n                .OldAnnotation(\"MySql:ValueGenerationStrategy\", MySqlValueGenerationStrategy.IdentityColumn);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250606115441_ForceCredentialsChange.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250606115441_ForceCredentialsChange\")]\n    partial class ForceCredentialsChange\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250606115441_ForceCredentialsChange.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class ForceCredentialsChange : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<bool>(\n                name: \"NeedsNewCredentials\",\n                table: \"AspNetUsers\",\n                type: \"tinyint(1)\",\n                nullable: false,\n                defaultValue: false);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"NeedsNewCredentials\",\n                table: \"AspNetUsers\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250615181842_TextToNameCard.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250615181842_TextToNameCard\")]\n    partial class TextToNameCard\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250615181842_TextToNameCard.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class TextToNameCard : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.RenameColumn(\n                name: \"Text\",\n                table: \"Labels\",\n                newName: \"Name\");\n\n            migrationBuilder.RenameColumn(\n                name: \"Text\",\n                table: \"Cards\",\n                newName: \"Name\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.RenameColumn(\n                name: \"Name\",\n                table: \"Labels\",\n                newName: \"Text\");\n\n            migrationBuilder.RenameColumn(\n                name: \"Name\",\n                table: \"Cards\",\n                newName: \"Text\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250617140549_SnoozeCards.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250617140549_SnoozeCards\")]\n    partial class SnoozeCards\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250617140549_SnoozeCards.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class SnoozeCards : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"SnoozedUntil\",\n                table: \"Cards\",\n                type: \"datetime(6)\",\n                nullable: true);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"SnoozedUntil\",\n                table: \"Cards\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250618090806_AtRemoval.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250618090806_AtRemoval\")]\n    partial class AtRemoval\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250618090806_AtRemoval.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class AtRemoval : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"At\",\n                table: \"Activities\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"At\",\n                table: \"Activities\",\n                type: \"datetime(6)\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250618114219_SelfAssign.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250618114219_SelfAssign\")]\n    partial class SelfAssign\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250618114219_SelfAssign.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class SelfAssign : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<bool>(\n                name: \"AutomaticAssign\",\n                table: \"AspNetUsers\",\n                type: \"tinyint(1)\",\n                nullable: false,\n                defaultValue: false);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"AutomaticAssign\",\n                table: \"AspNetUsers\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250703124731_DisableBoardAnimations.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250703124731_DisableBoardAnimations\")]\n    partial class DisableBoardAnimations\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250703124731_DisableBoardAnimations.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class DisableBoardAnimations : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<bool>(\n                name: \"DisableSortingAnimations\",\n                table: \"Boards\",\n                type: \"tinyint(1)\",\n                nullable: false,\n                defaultValue: false);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"DisableSortingAnimations\",\n                table: \"Boards\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250709130027_RepeatingCards.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250709130027_RepeatingCards\")]\n    partial class RepeatingCards\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250709130027_RepeatingCards.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class RepeatingCards : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<int>(\n                name: \"RepeatInfo_CardPlacement\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"RepeatInfo_LastRepeat\",\n                table: \"Cards\",\n                type: \"datetime(6)\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<int>(\n                name: \"RepeatInfo_Number\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<string>(\n                name: \"RepeatInfo_Selected\",\n                table: \"Cards\",\n                type: \"longtext\",\n                nullable: true)\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.AddColumn<int>(\n                name: \"RepeatInfo_TargetColumnId\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<TimeOnly>(\n                name: \"RepeatInfo_Time\",\n                table: \"Cards\",\n                type: \"time(6)\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<int>(\n                name: \"RepeatInfo_Type\",\n                table: \"Cards\",\n                type: \"int\",\n                nullable: true);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_CardPlacement\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_LastRepeat\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_Number\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_Selected\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_TargetColumnId\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_Time\",\n                table: \"Cards\");\n\n            migrationBuilder.DropColumn(\n                name: \"RepeatInfo_Type\",\n                table: \"Cards\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250826115734_NewCardPlacement.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20250826115734_NewCardPlacement\")]\n    partial class NewCardPlacement\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<bool>(\"Blocked\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"NewCardPlacement\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20250826115734_NewCardPlacement.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class NewCardPlacement : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<int>(\n                name: \"NewCardPlacement\",\n                table: \"Columns\",\n                type: \"int\",\n                nullable: false,\n                defaultValue: 0);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"NewCardPlacement\",\n                table: \"Columns\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251005111419_BlockToFlagged.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20251005111419_BlockToFlagged\")]\n    partial class BlockToFlagged\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"Flagged\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"NewCardPlacement\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251005111419_BlockToFlagged.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class BlockToFlagged : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.RenameColumn(\n                name: \"Blocked\",\n                table: \"Cards\",\n                newName: \"Flagged\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.RenameColumn(\n                name: \"Flagged\",\n                table: \"Cards\",\n                newName: \"Blocked\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251005174743_SubtaskAssignee.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20251005174743_SubtaskAssignee\")]\n    partial class SubtaskAssignee\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.5\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"SubtasksId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssigneesId\", \"SubtasksId\");\n\n                    b.HasIndex(\"SubtasksId\");\n\n                    b.ToTable(\"SubtaskUser\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"Flagged\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"NewCardPlacement\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Subtask\", null)\n                        .WithMany()\n                        .HasForeignKey(\"SubtasksId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251005174743_SubtaskAssignee.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class SubtaskAssignee : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.CreateTable(\n                name: \"SubtaskUser\",\n                columns: table => new\n                {\n                    AssigneesId = table.Column<int>(type: \"int\", nullable: false),\n                    SubtasksId = table.Column<int>(type: \"int\", nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_SubtaskUser\", x => new { x.AssigneesId, x.SubtasksId });\n                    table.ForeignKey(\n                        name: \"FK_SubtaskUser_AspNetUsers_AssigneesId\",\n                        column: x => x.AssigneesId,\n                        principalTable: \"AspNetUsers\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                    table.ForeignKey(\n                        name: \"FK_SubtaskUser_Subtasks_SubtasksId\",\n                        column: x => x.SubtasksId,\n                        principalTable: \"Subtasks\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                })\n                .Annotation(\"MySql:CharSet\", \"utf8mb4\");\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_SubtaskUser_SubtasksId\",\n                table: \"SubtaskUser\",\n                column: \"SubtasksId\");\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"SubtaskUser\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251011134337_Information.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    [Migration(\"20251011134337_Information\")]\n    partial class Information\n    {\n        /// <inheritdoc />\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.9\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"SubtasksId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssigneesId\", \"SubtasksId\");\n\n                    b.HasIndex(\"SubtasksId\");\n\n                    b.ToTable(\"SubtaskUser\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"Flagged\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"NewCardPlacement\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime?>(\"InformationSnoozeUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastViewedInformation\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Subtask\", null)\n                        .WithMany()\n                        .HasForeignKey(\"SubtasksId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/20251011134337_Information.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    /// <inheritdoc />\n    public partial class Information : Migration\n    {\n        /// <inheritdoc />\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"InformationSnoozeUntil\",\n                table: \"AspNetUsers\",\n                type: \"datetime(6)\",\n                nullable: true);\n\n            migrationBuilder.AddColumn<int>(\n                name: \"LastViewedInformation\",\n                table: \"AspNetUsers\",\n                type: \"int\",\n                nullable: true);\n        }\n\n        /// <inheritdoc />\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"InformationSnoozeUntil\",\n                table: \"AspNetUsers\");\n\n            migrationBuilder.DropColumn(\n                name: \"LastViewedInformation\",\n                table: \"AspNetUsers\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Migrations/DataContextModelSnapshot.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Metadata;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Ticky.Internal.Data;\n\n#nullable disable\n\nnamespace Ticky.Internal.Migrations\n{\n    [DbContext(typeof(DataContext))]\n    partial class DataContextModelSnapshot : ModelSnapshot\n    {\n        protected override void BuildModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"ProductVersion\", \"9.0.9\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 64);\n\n            MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.Property<int>(\"LabelsId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OnCardsId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LabelsId\", \"OnCardsId\");\n\n                    b.HasIndex(\"OnCardsId\");\n\n                    b.ToTable(\"CardLabel\");\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.Property<int>(\"AssignedToId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssignedToId\", \"AssigneesId\");\n\n                    b.HasIndex(\"AssigneesId\");\n\n                    b.ToTable(\"CardUser\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"FriendlyName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Xml\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"DataProtectionKeys\");\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Name\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"RoleNameIndex\");\n\n                    b.ToTable(\"AspNetRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetRoleClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"ClaimType\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"ClaimValue\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserClaims\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderKey\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"ProviderDisplayName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"LoginProvider\", \"ProviderKey\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"AspNetUserLogins\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"RoleId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"UserId\", \"RoleId\");\n\n                    b.HasIndex(\"RoleId\");\n\n                    b.ToTable(\"AspNetUserRoles\", (string)null);\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"LoginProvider\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Name\")\n                        .HasColumnType(\"varchar(255)\");\n\n                    b.Property<string>(\"Value\")\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"UserId\", \"LoginProvider\", \"Name\");\n\n                    b.ToTable(\"AspNetUserTokens\", (string)null);\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.Property<int>(\"AssigneesId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"SubtasksId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"AssigneesId\", \"SubtasksId\");\n\n                    b.HasIndex(\"SubtasksId\");\n\n                    b.ToTable(\"SubtaskUser\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Activities\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"FileName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"OriginalName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Attachments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<string>(\"Code\")\n                        .IsRequired()\n                        .HasMaxLength(5)\n                        .HasColumnType(\"varchar(5)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"DisableSortingAnimations\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.ToTable(\"Boards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"BoardMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"ColumnId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"Deadline\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"DeadlineProcessed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"Description\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"Flagged\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"Number\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"Priority\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime?>(\"SnoozedUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ColumnId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardOneId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"CardTwoId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Category\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardOneId\");\n\n                    b.HasIndex(\"CardTwoId\");\n\n                    b.ToTable(\"CardLinks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CodePurpose\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Value\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"UserId\")\n                        .IsUnique();\n\n                    b.ToTable(\"Codes\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Collapsed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"Finished\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"MaxCards\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"NewCardPlacement\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"OrderRule\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Columns\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CreatedById\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"CreatedById\");\n\n                    b.ToTable(\"Comments\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"Favorites\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BackgroundColor\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<int>(\"TextColor\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.ToTable(\"Labels\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"BoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"VisitTime\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"BoardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"LastVisits\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"Name\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.ToTable(\"Projects\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"AddedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"IsAdmin\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int>(\"ProjectId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"ProjectId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"ProjectMemberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<DateTime>(\"At\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Reminders\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"Completed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"Index\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<string>(\"Text\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.ToTable(\"Subtasks\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"CardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime?>(\"EndedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<DateTime>(\"StartedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<int>(\"UserId\")\n                        .HasColumnType(\"int\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"CardId\");\n\n                    b.HasIndex(\"UserId\");\n\n                    b.ToTable(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Property<int>(\"Id\")\n                        .ValueGeneratedOnAdd()\n                        .HasColumnType(\"int\");\n\n                    MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>(\"Id\"));\n\n                    b.Property<int>(\"AccessFailedCount\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"AutomaticAssign\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticCardEdit\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<bool>(\"AutomaticDeadlineReminder\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ConcurrencyStamp\")\n                        .IsConcurrencyToken()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<DateTime>(\"CreatedAt\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<string>(\"DisplayName\")\n                        .IsRequired()\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"Email\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<bool>(\"EmailConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTime?>(\"InformationSnoozeUntil\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"InstantDelete\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<int?>(\"LastViewedInformation\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<int?>(\"LastVisitedBoardId\")\n                        .HasColumnType(\"int\");\n\n                    b.Property<bool>(\"LockoutEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<DateTimeOffset?>(\"LockoutEnd\")\n                        .HasColumnType(\"datetime(6)\");\n\n                    b.Property<bool>(\"NeedsNewCredentials\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"NormalizedEmail\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"NormalizedUserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.Property<string>(\"PasswordHash\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"PhoneNumber\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"PhoneNumberConfirmed\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"ProfilePictureFileName\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<string>(\"SecurityStamp\")\n                        .HasColumnType(\"longtext\");\n\n                    b.Property<bool>(\"TwoFactorEnabled\")\n                        .HasColumnType(\"tinyint(1)\");\n\n                    b.Property<string>(\"UserName\")\n                        .HasMaxLength(256)\n                        .HasColumnType(\"varchar(256)\");\n\n                    b.HasKey(\"Id\");\n\n                    b.HasIndex(\"NormalizedEmail\")\n                        .HasDatabaseName(\"EmailIndex\");\n\n                    b.HasIndex(\"NormalizedUserName\")\n                        .IsUnique()\n                        .HasDatabaseName(\"UserNameIndex\");\n\n                    b.ToTable(\"AspNetUsers\", (string)null);\n                });\n\n            modelBuilder.Entity(\"CardLabel\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Label\", null)\n                        .WithMany()\n                        .HasForeignKey(\"LabelsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"OnCardsId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"CardUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssignedToId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserClaim<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserLogin<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserRole<int>\", b =>\n                {\n                    b.HasOne(\"Microsoft.AspNetCore.Identity.IdentityRole<int>\", null)\n                        .WithMany()\n                        .HasForeignKey(\"RoleId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Microsoft.AspNetCore.Identity.IdentityUserToken<int>\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"SubtaskUser\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", null)\n                        .WithMany()\n                        .HasForeignKey(\"AssigneesId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Subtask\", null)\n                        .WithMany()\n                        .HasForeignKey(\"SubtasksId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Activity\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Activities\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Attachment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Attachments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Boards\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.BoardMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"BoardMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Column\", \"Column\")\n                        .WithMany(\"Cards\")\n                        .HasForeignKey(\"ColumnId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedCards\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.OwnsOne(\"Ticky.Base.Entities.Owned.RepeatInfo\", \"RepeatInfo\", b1 =>\n                        {\n                            b1.Property<int>(\"CardId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<int>(\"CardPlacement\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<DateTime>(\"LastRepeat\")\n                                .HasColumnType(\"datetime(6)\");\n\n                            b1.Property<int?>(\"Number\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<string>(\"Selected\")\n                                .HasColumnType(\"longtext\");\n\n                            b1.Property<int?>(\"TargetColumnId\")\n                                .HasColumnType(\"int\");\n\n                            b1.Property<TimeOnly>(\"Time\")\n                                .HasColumnType(\"time(6)\");\n\n                            b1.Property<int>(\"Type\")\n                                .HasColumnType(\"int\");\n\n                            b1.HasKey(\"CardId\");\n\n                            b1.ToTable(\"Cards\");\n\n                            b1.WithOwner()\n                                .HasForeignKey(\"CardId\");\n                        });\n\n                    b.Navigation(\"Column\");\n\n                    b.Navigation(\"CreatedBy\");\n\n                    b.Navigation(\"RepeatInfo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.CardLink\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardOne\")\n                        .WithMany(\"LinkedIssuesOne\")\n                        .HasForeignKey(\"CardOneId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"CardTwo\")\n                        .WithMany(\"LinkedIssuesTwo\")\n                        .HasForeignKey(\"CardTwoId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"CardOne\");\n\n                    b.Navigation(\"CardTwo\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Code\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithOne(\"EmailVerificationCode\")\n                        .HasForeignKey(\"Ticky.Base.Entities.Code\", \"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Columns\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Comment\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Comments\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"CreatedBy\")\n                        .WithMany(\"CreatedComments\")\n                        .HasForeignKey(\"CreatedById\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"CreatedBy\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Favorite\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"Favorites\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Label\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"Labels\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.LastVisit\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Board\", \"Board\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"BoardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"LastVisits\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Board\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.ProjectMembership\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Project\", \"Project\")\n                        .WithMany(\"Memberships\")\n                        .HasForeignKey(\"ProjectId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"ProjectMemberships\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Project\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Reminder\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Reminders\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Subtask\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"Subtasks\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.TimeRecord\", b =>\n                {\n                    b.HasOne(\"Ticky.Base.Entities.Card\", \"Card\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"CardId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.HasOne(\"Ticky.Base.Entities.User\", \"User\")\n                        .WithMany(\"TimeRecords\")\n                        .HasForeignKey(\"UserId\")\n                        .OnDelete(DeleteBehavior.Cascade)\n                        .IsRequired();\n\n                    b.Navigation(\"Card\");\n\n                    b.Navigation(\"User\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Board\", b =>\n                {\n                    b.Navigation(\"Columns\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"Labels\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Card\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"Attachments\");\n\n                    b.Navigation(\"Comments\");\n\n                    b.Navigation(\"LinkedIssuesOne\");\n\n                    b.Navigation(\"LinkedIssuesTwo\");\n\n                    b.Navigation(\"Reminders\");\n\n                    b.Navigation(\"Subtasks\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Column\", b =>\n                {\n                    b.Navigation(\"Cards\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.Project\", b =>\n                {\n                    b.Navigation(\"Boards\");\n\n                    b.Navigation(\"Memberships\");\n                });\n\n            modelBuilder.Entity(\"Ticky.Base.Entities.User\", b =>\n                {\n                    b.Navigation(\"Activities\");\n\n                    b.Navigation(\"BoardMemberships\");\n\n                    b.Navigation(\"CreatedCards\");\n\n                    b.Navigation(\"CreatedComments\");\n\n                    b.Navigation(\"EmailVerificationCode\");\n\n                    b.Navigation(\"Favorites\");\n\n                    b.Navigation(\"LastVisits\");\n\n                    b.Navigation(\"ProjectMemberships\");\n\n                    b.Navigation(\"TimeRecords\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/AvatarService.cs",
    "content": "namespace Ticky.Internal.Services\n{\n    public class AvatarService\n    {\n        private readonly HttpClient _httpClient;\n\n        public AvatarService(HttpClient httpClient)\n        {\n            _httpClient = httpClient;\n        }\n\n        public async Task<string> FetchAvatarAsync(string name)\n        {\n            if (!Directory.Exists(Constants.SAVE_UPLOADED_PATH))\n                Directory.CreateDirectory(Constants.SAVE_UPLOADED_PATH);\n\n            if (!Directory.Exists(Constants.SAVE_UPLOADED_IMAGES_PATH))\n                Directory.CreateDirectory(Constants.SAVE_UPLOADED_IMAGES_PATH);\n\n            var fileName = name + \".png\";\n            var targetFilePath = $\"{Constants.SAVE_UPLOADED_IMAGES_PATH}/{fileName}\";\n\n            if (File.Exists(targetFilePath))\n                return fileName;\n\n            if (!Constants.FULLY_OFFLINE)\n            {\n                var stream = await _httpClient.GetStreamAsync(\n                    $\"https://ui-avatars.com/api/?background=random&name={Uri.EscapeDataString(name)}\"\n                );\n                using var fs = File.Create(targetFilePath);\n                stream.CopyTo(fs);\n            }\n            else\n            {\n                File.Copy(\n                    Path.Combine(Constants.WWW_ROOT, \"images\", \"question_mark_avatar.png\"),\n                    targetFilePath\n                );\n            }\n            return fileName;\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/CardNumberingService.cs",
    "content": "﻿namespace Ticky.Internal.Services;\n\npublic class CardNumberingService\n{\n    private readonly IDbContextFactory<DataContext> _dbContextFactory;\n\n    public CardNumberingService(IDbContextFactory<DataContext> dbContextFactory)\n    {\n        _dbContextFactory = dbContextFactory;\n    }\n\n    public async Task<int> GetNextNumberAsync(int boardId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        return (\n                await db\n                    .Cards.Include(x => x.Column)\n                    .Where(x => x.Column.BoardId.Equals(boardId))\n                    .MaxAsync(x => (int?)x.Number) ?? 0\n            ) + 1;\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/CodeService.cs",
    "content": "﻿using Microsoft.EntityFrameworkCore;\n\nnamespace Ticky.Internal.Services;\n\npublic class CodeService\n{\n    private readonly DataContext _dataContext;\n\n    public CodeService(DataContext dataContext)\n    {\n        _dataContext = dataContext;\n    }\n\n    public async Task<Code> CreateCodeAsync(User account, CodePurpose codePurpose)\n    {\n        var code = new Code\n        {\n            UserId = account.Id,\n            CodePurpose = codePurpose,\n            Value = await GetUnusedCodeAsync(),\n            CreatedAt = DateTime.Now\n        };\n\n        account.EmailVerificationCode = code;\n        _dataContext.Update(account);\n        await _dataContext.SaveChangesAsync();\n\n        return code;\n    }\n\n    private async Task<string> GetUnusedCodeAsync()\n    {\n        const string alphabet = \"123456789\";\n        var random = new Random();\n\n        do\n        {\n            string code = string.Empty;\n\n            for (int i = 0; i < 3; i++)\n            {\n                code += alphabet[random.Next(alphabet.Length - 1)];\n            }\n\n            code += \"-\";\n\n            for (int i = 0; i < 3; i++)\n            {\n                code += alphabet[random.Next(alphabet.Length - 1)];\n            }\n\n            var match = await _dataContext.Codes.AnyAsync(x => x.Value.Equals(code));\n\n            if (!match)\n                return code;\n        } while (true);\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/EmailService.cs",
    "content": "using Devity.Extensions.Templates;\nusing Devity.Mailing;\nusing Devity.NETCore.MailKit.Core;\n\nnamespace Ticky.Internal.Services\n{\n    public class EmailService(IEmailService emailService, ILogger<EmailService> logger)\n        : CommonMailService(emailService, $\"{TITLE_KEY} | {Constants.APP_NAME}\")\n    {\n        private static readonly string VERIFY_EMAIL = Path.Combine(\n            Constants.Emails.BASE_PATH,\n            \"VerifyEmail.html\"\n        );\n        private static readonly string FORGOTTEN_PASSWORD = Path.Combine(\n            Constants.Emails.BASE_PATH,\n            \"ForgottenPassword.html\"\n        );\n        private static readonly string REMINDER = Path.Combine(\n            Constants.Emails.BASE_PATH,\n            \"Reminder.html\"\n        );\n        private static readonly string DEADLINE_REMINDER = Path.Combine(\n            Constants.Emails.BASE_PATH,\n            \"DeadlineReminder.html\"\n        );\n\n        public async Task SendVerificationEmailAsync(string emailAddress, Code code) =>\n            await SendDevityEmailAsync(\n                new DevityEmail(\n                    emailAddress,\n                    \"Verify e-mail\",\n                    new DevityTemplate(VERIFY_EMAIL).AddKey(\n                        Constants.Emails.Mappings.VERIFICATION_CODE,\n                        code.Value\n                    )\n                )\n            );\n\n        public async Task SendReminderEmailAsync(string emailAddress, Reminder reminder)\n        {\n            var cardCode = $\"{reminder.Card.Column.Board.Code}-{reminder.Card.Number}\";\n            var cardPath = $\"/boards/{reminder.Card.Column.BoardId}/{reminder.Card.Id}\";\n\n            await SendDevityEmailAsync(\n                new DevityEmail(\n                    emailAddress,\n                    $\"Reminder: {reminder.Card.Name} ({cardCode})\",\n                    new DevityTemplate(REMINDER)\n                        .AddKey(Constants.Emails.Mappings.CARD_TEXT, reminder.Card.Name)\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_SCHEDULED_FOR,\n                            reminder.At.ToReadableStringWithTime()\n                        )\n                        .AddKey(Constants.Emails.Mappings.CARD_CODE, cardCode)\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_DESCRIPTION,\n                            reminder.Card.Description\n                        )\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_URL,\n                            $\"{Constants.BASE_URL}{cardPath}\"\n                        )\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_DEADLINE,\n                            reminder.Card.Deadline.GetValueOrDefault().ToReadableStringWithTime()\n                        )\n                        .AddCondition(\n                            Constants.Emails.Mappings.CARD_DEADLINE_SECTION,\n                            reminder.Card.Deadline.HasValue\n                        )\n                        .AddCondition(\n                            Constants.Emails.Mappings.CARD_DESCRIPTION_SECTION,\n                            !string.IsNullOrWhiteSpace(reminder.Card.Description)\n                        )\n                        .AddCondition(\n                            Constants.Emails.Mappings.CARD_SUBTASKS_SECTION,\n                            reminder.Card.Subtasks.Any()\n                        )\n                        .AddLoop(\n                            Constants.Emails.Mappings.CARD_SUBTASKS,\n                            new DevityTemplateLoop<Subtask>(reminder.Card.Subtasks)\n                                .AddKey(Constants.Emails.Mappings.SUBTASK_TEXT, s => s.Text)\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_ICON,\n                                    s => s.Completed ? \"✓\" : \"○\"\n                                )\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_ICON_COLOR,\n                                    s => s.Completed ? \"#4CAF50\" : \"#F44336\"\n                                )\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_COMPLETED_CLASS,\n                                    s => s.Completed ? \" subtask-completed\" : string.Empty\n                                )\n                        )\n                )\n            );\n        }\n\n        public async Task SendDeadlineReminderEmailAsync(string emailAddress, Card card)\n        {\n            var cardCode = $\"{card.Column.Board.Code}-{card.Number}\";\n            var cardPath = $\"/boards/{card.Column.BoardId}/{card.Id}\";\n\n            await SendDevityEmailAsync(\n                new DevityEmail(\n                    emailAddress,\n                    $\"Deadline today: {card.Name} {cardCode}\",\n                    new DevityTemplate(DEADLINE_REMINDER)\n                        .AddKey(Constants.Emails.Mappings.CARD_TEXT, card.Name)\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_SCHEDULED_FOR,\n                            card.Deadline!.Value.ToReadableStringWithTime()\n                        )\n                        .AddKey(Constants.Emails.Mappings.CARD_CODE, cardCode)\n                        .AddKey(Constants.Emails.Mappings.CARD_DESCRIPTION, card.Description)\n                        .AddKey(\n                            Constants.Emails.Mappings.CARD_URL,\n                            $\"{Constants.BASE_URL}{cardPath}\"\n                        )\n                        .AddCondition(\n                            Constants.Emails.Mappings.CARD_DESCRIPTION_SECTION,\n                            !string.IsNullOrWhiteSpace(card.Description)\n                        )\n                        .AddCondition(\n                            Constants.Emails.Mappings.CARD_SUBTASKS_SECTION,\n                            card.Subtasks.Any()\n                        )\n                        .AddLoop(\n                            Constants.Emails.Mappings.CARD_SUBTASKS,\n                            new DevityTemplateLoop<Subtask>(card.Subtasks)\n                                .AddKey(Constants.Emails.Mappings.SUBTASK_TEXT, s => s.Text)\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_ICON,\n                                    s => s.Completed ? \"✓\" : \"○\"\n                                )\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_ICON_COLOR,\n                                    s => s.Completed ? \"#4CAF50\" : \"#F44336\"\n                                )\n                                .AddKey(\n                                    Constants.Emails.Mappings.SUBTASK_COMPLETED_CLASS,\n                                    s => s.Completed ? \" subtask-completed\" : string.Empty\n                                )\n                        )\n                )\n            );\n        }\n\n        public async Task SendForgottenPasswordCodeEmailAsync(string emailAddress, Code code) =>\n            await SendDevityEmailAsync(\n                new DevityEmail(\n                    emailAddress,\n                    \"Forgotten password\",\n                    new DevityTemplate(FORGOTTEN_PASSWORD).AddKey(\n                        Constants.Emails.Mappings.VERIFICATION_CODE,\n                        code.Value\n                    )\n                )\n            );\n\n        private async Task SendDevityEmailAsync(DevityEmail devityEmail)\n        {\n            if (!Constants.SMTP_ENABLED)\n            {\n                logger.LogInformation(\"SMTP disabled, could not send e-mail.\");\n                return;\n            }\n\n            await base.SendEmailAsync(devityEmail);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/Hosted/AbstractHostedService.cs",
    "content": "using Microsoft.Extensions.Hosting;\n\nnamespace Ticky.Internal.Services.Hosted;\n\npublic abstract class AbstractHostedService<T> : IHostedService\n{\n    protected ILogger<T> Logger { get; set; }\n    protected readonly IServiceScopeFactory ServiceScopeFactory;\n    private Timer _timer;\n    private bool _unrealizedChange;\n    private TimeSpan _untilStart;\n    private TimeSpan _frequency;\n\n    protected AbstractHostedService(\n        IServiceScopeFactory serviceScopeFactory,\n        TimeSpan untilStart,\n        TimeSpan frequency\n    )\n    {\n        if (untilStart < TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY))\n            throw new Exception(\n                $\"A hosted service cannot have a minimum time shorter than {Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY} seconds.\"\n            );\n        ServiceScopeFactory = serviceScopeFactory;\n        _untilStart = untilStart;\n        _frequency = frequency;\n        _timer = new(DoWork, null, untilStart, frequency);\n        Logger = ServiceScopeFactory\n            .CreateScope()\n            .ServiceProvider.GetRequiredService<ILogger<T>>()!;\n    }\n\n    public Task StartAsync(CancellationToken cancellationToken)\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n\n        Logger.LogDebug(\"{Name} starting.\", GetType().Name);\n\n        OnStart();\n\n        return Task.CompletedTask;\n    }\n\n    public Task StopAsync(CancellationToken cancellationToken)\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n\n        Logger.LogDebug(\"{Name} stopping.\", GetType().Name);\n\n        _timer!.Change(Timeout.Infinite, 0);\n        Dispose();\n        OnStop();\n        return Task.CompletedTask;\n    }\n\n    private async void DoWork(object? state)\n    {\n        try\n        {\n            var startedAt = DateTime.Now;\n            using var scope = ServiceScopeFactory.CreateScope();\n\n            Logger.LogDebug(\"{Name} job running.\", GetType().Name);\n\n            await OnRun();\n\n            Logger.LogDebug(\n                \"{Name} job finished, next run will happen at {GetNextRunDateTime}.\", GetType().Name, GetNextRunDateTime(startedAt)\n            );\n        } \n        catch (Exception ex)\n        {\n            Logger.LogError(ex, ex.Message);\n        }\n    }\n\n    private string GetNextRunDateTime(DateTime startedAt)\n    {\n        if (_unrealizedChange)\n        {\n            _unrealizedChange = false;\n            return startedAt.AddSeconds(_untilStart.TotalSeconds).ToReadableStringWithTime();\n        }\n        else\n            return startedAt.AddSeconds(_frequency.TotalSeconds).ToReadableStringWithTime();\n    }\n\n    protected void ChangeTimer(TimeSpan untilStart, TimeSpan frequency)\n    {\n        _unrealizedChange = true;\n        _untilStart = untilStart;\n        _frequency = frequency;\n        _timer.Change(_untilStart, _frequency);\n    }\n\n    protected virtual void OnStart() { }\n\n    protected virtual void OnStop() { }\n\n    protected virtual Task OnRun()\n    {\n        return Task.CompletedTask;\n    }\n\n    public void Dispose()\n    {\n        _timer!.Dispose();\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/Hosted/CleanupHostedService.cs",
    "content": "namespace Ticky.Internal.Services.Hosted;\n\npublic class CleanupHostedService(IServiceScopeFactory serviceScopeFactory)\n    : AbstractHostedService<CleanupHostedService>(serviceScopeFactory, TimeSpan.FromMinutes(15), TimeSpan.FromHours(1))\n{\n    protected override async Task OnRun()\n    {\n        await CleanCodes();\n        await DeleteUnusedProfilePictures();\n        await DeleteUnlinkedAttachments();\n    }\n\n    private async Task CleanCodes()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n\n        var codesForDeletion = await db\n            .Codes.Include(x => x.User)\n            .Where(x =>\n                DateTime.Now.AddHours(-1) > x.CreatedAt || (x.User != null && x.User.EmailConfirmed)\n            )\n            .ToListAsync();\n        int deletedAccounts = 0;\n\n        foreach (var code in codesForDeletion)\n        {\n            if (code.User is not null && !code.User.EmailConfirmed)\n            {\n                db.Users.Remove(code.User);\n                deletedAccounts++;\n            }\n\n            db.Codes.Remove(code);\n        }\n\n        if (codesForDeletion.Any())\n        {\n            await db.SaveChangesAsync();\n            Logger.LogInformation(\n                $\"{codesForDeletion.Count} codes have been deleted alongside {deletedAccounts} unconfirmed accounts.\"\n            );\n        }\n    }\n\n    private async Task DeleteUnusedProfilePictures()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n        var allProfilePictureNames = await db\n            .Users.Select(x => x.ProfilePictureFileName)\n            .Where(x => x != null)\n            .ToListAsync();\n\n        var folderPath = Constants.SAVE_UPLOADED_IMAGES_PATH;\n\n        if (!Directory.Exists(folderPath))\n            Directory.CreateDirectory(folderPath);\n\n        var unlinkedUploadedImages = Directory\n            .GetFiles(folderPath)\n            .Where(x =>\n                !allProfilePictureNames.Contains(\n                    x[(Math.Max(x.LastIndexOf('/'), x.LastIndexOf('\\\\')) + 1)..]\n                )\n            )\n            .ToList();\n\n        foreach (var unlinkedUploadedImage in unlinkedUploadedImages)\n        {\n            File.Delete(unlinkedUploadedImage);\n        }\n\n        if (unlinkedUploadedImages.Any())\n            Logger.LogInformation(\n                $\"{unlinkedUploadedImages.Count} images have been deleted due to being unlinked.\"\n            );\n    }\n\n    private async Task DeleteUnlinkedAttachments()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n        var allFileNames = await db.Attachments.Select(x => x.FileName).ToListAsync();\n\n        var folderPath = Constants.SAVE_UPLOADED_FILES_PATH;\n\n        if (!Directory.Exists(folderPath))\n            Directory.CreateDirectory(folderPath);\n\n        var unlinkedAttachments = Directory\n            .GetFiles(folderPath)\n            .Where(x =>\n                !allFileNames.Contains(x[(Math.Max(x.LastIndexOf('/'), x.LastIndexOf('\\\\')) + 1)..])\n            )\n            .ToList();\n\n        foreach (var unlinkedAttachment in unlinkedAttachments)\n        {\n            File.Delete(unlinkedAttachment);\n        }\n\n        if (unlinkedAttachments.Any())\n            Logger.LogInformation(\n                $\"{unlinkedAttachments.Count} attachments have been deleted due to being unlinked.\"\n            );\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/Hosted/ReminderHostedService.cs",
    "content": "namespace Ticky.Internal.Services.Hosted;\n\npublic class ReminderHostedService(IServiceScopeFactory serviceScopeFactory)\n    : AbstractHostedService<ReminderHostedService>(serviceScopeFactory,\n        TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY),\n        TimeSpan.FromMinutes(2))\n{\n    protected override async Task OnRun()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n        var mailService = scope.ServiceProvider.GetRequiredService<EmailService>()!;\n\n        var onTimeReminders = await db\n            .Reminders.Include(x => x.Card)\n            .ThenInclude(x => x.Column)\n            .ThenInclude(x => x.Board)\n            .Include(x => x.Card)\n            .ThenInclude(x => x.Assignees)\n            .Include(x => x.Card)\n            .ThenInclude(x => x.CreatedBy)\n            .Include(x => x.Card)\n            .ThenInclude(x => x.Subtasks)\n            .Where(x => DateTime.Now > x.At)\n            .ToListAsync();\n\n        foreach (var reminder in onTimeReminders)\n        {\n            var recipients = new HashSet<string>();\n\n            foreach (var assignee in reminder.Card.Assignees)\n                recipients.Add(assignee.Email!);\n\n            recipients.Add(reminder.Card.CreatedBy.Email!);\n\n            foreach (var email in recipients)\n            {\n                try\n                {\n                    await mailService.SendReminderEmailAsync(email, reminder);\n                }\n                catch (Exception ex)\n                {\n                    Logger.LogError($\"Failed to send reminder to {email}. Error: {ex}\");\n                }\n            }\n        }\n\n        if (onTimeReminders.Any())\n        {\n            db.Reminders.RemoveRange(onTimeReminders);\n            await db.SaveChangesAsync();\n            Logger.LogInformation($\"{onTimeReminders.Count} reminders have been sent.\");\n        }\n\n        var cardsAtDeadline = await db\n            .Cards.Include(x => x.Column)\n            .ThenInclude(x => x.Board)\n            .Include(x => x.Assignees)\n            .Include(x => x.Subtasks)\n            .Include(x => x.CreatedBy)\n            .Where(x =>\n                x.Deadline != null\n                && !x.DeadlineProcessed\n                && x.Deadline.Value.Date.Equals(DateTime.Today.Date)\n            )\n            .ToListAsync();\n\n        int sentReminders = 0;\n\n        foreach (var card in cardsAtDeadline)\n        {\n            var recipients = new HashSet<string>();\n\n            foreach (var assignee in card.Assignees)\n            {\n                if (assignee.AutomaticDeadlineReminder)\n                    recipients.Add(assignee.Email!);\n            }\n\n            if (card.CreatedBy.AutomaticDeadlineReminder)\n                recipients.Add(card.CreatedBy.Email!);\n\n            foreach (var email in recipients)\n            {\n                try\n                {\n                    await mailService.SendDeadlineReminderEmailAsync(email, card);\n                    sentReminders++;\n                }\n                catch (Exception ex)\n                {\n                    Logger.LogError($\"Failed to send deadline reminder to {email}. Error: {ex}\");\n                }\n            }\n\n            card.DeadlineProcessed = true;\n        }\n\n        if (cardsAtDeadline.Any())\n        {\n            await db.SaveChangesAsync();\n            Logger.LogInformation($\"{cardsAtDeadline.Count} deadline reminders have been sent.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/Hosted/RepeatHostedService.cs",
    "content": "namespace Ticky.Internal.Services.Hosted;\n\npublic class RepeatHostedService(IServiceScopeFactory serviceScopeFactory) : AbstractHostedService<RepeatHostedService>(\n    serviceScopeFactory,\n    TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY),\n    TimeSpan.FromMinutes(2))\n{\n    protected override async Task OnRun()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n        var logger = scope.ServiceProvider.GetRequiredService<ILogger<RepeatHostedService>>()!;\n        var cardNumberingService =\n            scope.ServiceProvider.GetRequiredService<CardNumberingService>()!;\n\n        var allRepeatCards = await db.Cards.Where(x => x.RepeatInfo != null).ToListAsync();\n\n        var pendingNextRepeatCardIds = allRepeatCards\n            .Where(x => x.CalculateNextRepeat(DateTime.Now) < DateTime.Now)\n            .Select(x => x.Id)\n            .ToList();\n\n        var populatedPendingRepeatCards = await db\n            .Cards.Include(x => x.Column)\n            .ThenInclude(x => x.Board)\n            .Include(x => x.Subtasks)\n            .Include(x => x.Assignees)\n            .Include(x => x.Labels)\n            .Include(x => x.Attachments)\n            .Include(x => x.Reminders)\n            .Include(x => x.LinkedIssuesOne)\n            .Include(x => x.LinkedIssuesTwo)\n            .Where(x => pendingNextRepeatCardIds.Contains(x.Id))\n            .AsSplitQuery()\n            .ToListAsync();\n\n        foreach (var card in populatedPendingRepeatCards)\n        {\n            card.RepeatInfo!.LastRepeat = DateTime.Now;\n\n            var targetColumn = await db\n                .Columns.Where(x => x.Id.Equals(card.RepeatInfo.TargetColumnId))\n                .Include(x => x.Cards)\n                .FirstOrDefaultAsync();\n\n            if (targetColumn is null)\n                targetColumn = await db\n                    .Columns.Where(x => x.BoardId.Equals(card.Column.BoardId))\n                    .Include(x => x.Cards)\n                    .OrderBy(x => x.Index)\n                    .FirstOrDefaultAsync();\n\n            if (targetColumn is null)\n            {\n                targetColumn = new Column()\n                {\n                    BoardId = card.Column.BoardId,\n                    Name = \"Default\",\n                    Index = 0\n                };\n\n                db.Columns.Add(targetColumn);\n            }\n\n            var newCard = new Card\n            {\n                Name = card.Name,\n                Description = card.Description,\n                Deadline = card.Deadline,\n                Priority = card.Priority,\n                CreatedById = card.CreatedById,\n                SnoozedUntil = card.SnoozedUntil,\n                Flagged = card.Flagged,\n                ColumnId = targetColumn.Id,\n                Number = await cardNumberingService.GetNextNumberAsync(targetColumn.BoardId),\n                Index = 0,\n                Assignees = card.Assignees,\n                Labels = card.Labels\n            };\n\n            newCard.Attachments =\n            [\n                .. card.Attachments.Select(x => new Attachment()\n                {\n                    CardId = newCard.Id,\n                    FileName = x.FileName,\n                    OriginalName = x.OriginalName\n                })\n            ];\n            newCard.Reminders =\n            [\n                .. card.Reminders.Select(x => new Reminder() { CardId = newCard.Id, At = x.At })\n            ];\n            newCard.Subtasks =\n            [\n                .. card.Subtasks.Select(x => new Subtask()\n                {\n                    CardId = newCard.Id,\n                    Completed = x.Completed,\n                    Index = x.Index,\n                    Text = x.Text\n                })\n            ];\n\n            var identifier = $\"{card.Column.Board.Code}-{card.Number}\";\n\n            newCard.Activities.Add(\n                new()\n                {\n                    CardId = newCard.Id,\n                    Text = $\"<b>was repeated</b> from card <b>{identifier}</b>\",\n                    UserId = card.CreatedById\n                }\n            );\n\n            var oppositeCategory = Constants.LINK_TYPE_PAIRS.ContainsKey(Constants.REPEATED_KEY)\n                ? Constants.LINK_TYPE_PAIRS[Constants.REPEATED_KEY]\n                : Constants.LINK_TYPE_PAIRS.First(x => x.Value.Equals(Constants.REPEATED_KEY)).Key;\n\n            foreach (var linkedIssueOne in card.LinkedIssuesOne.Where(linkedIssueOne => !linkedIssueOne.Category.Equals(Constants.REPEATED_KEY)\n                         && !linkedIssueOne.Category.Equals(oppositeCategory)))\n            {\n                newCard.LinkedIssuesOne.Add(\n                    new()\n                    {\n                        CardOneId = newCard.Id,\n                        CardTwoId = linkedIssueOne.CardTwoId,\n                        Category = linkedIssueOne.Category\n                    }\n                );\n            }\n\n            foreach (var linkedIssueTwo in card.LinkedIssuesTwo.Where(linkedIssueTwo => !linkedIssueTwo.Category.Equals(Constants.REPEATED_KEY)\n                         && !linkedIssueTwo.Category.Equals(oppositeCategory)))\n            {\n                newCard.LinkedIssuesTwo.Add(\n                    new()\n                    {\n                        CardOneId = linkedIssueTwo.CardOneId,\n                        CardTwoId = newCard.Id,\n                        Category = linkedIssueTwo.Category\n                    }\n                );\n            }\n\n            newCard.LinkedIssuesOne.Add(\n                new()\n                {\n                    CardOneId = newCard.Id,\n                    CardTwoId = card.Id,\n                    Category = Constants.REPEATED_KEY\n                }\n            );\n\n            newCard.LinkedIssuesTwo.Add(\n                new()\n                {\n                    CardOneId = card.Id,\n                    CardTwoId = newCard.Id,\n                    Category = oppositeCategory\n                }\n            );\n\n            var newIdentifier = $\"{card.Column.Board.Code}-{newCard.Number}\";\n            card.Activities.Add(\n                new()\n                {\n                    CardId = card.Id,\n                    Text = $\"<b>created</b> repeat card <b>{newIdentifier}</b>\",\n                    UserId = card.CreatedById\n                }\n            );\n\n            targetColumn.Cards.Add(newCard);\n\n            if (card.RepeatInfo.CardPlacement.Equals(CardPlacement.Top))\n                targetColumn.Cards.ForEach(x => x.Index++);\n            else if (\n                card.RepeatInfo.CardPlacement.Equals(CardPlacement.Bottom)\n                && targetColumn.Cards.Count != 0\n            )\n                newCard.Index = targetColumn.Cards.Max(x => x.Index) + 1;\n            else\n                throw new Exception(\"Unsupported card placement type\");\n        }\n\n        if (populatedPendingRepeatCards.Count != 0)\n        {\n            await db.SaveChangesAsync();\n            logger.LogInformation(\"{Count} cards have been repeated.\", populatedPendingRepeatCards.Count);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/Hosted/SnoozeHostedService.cs",
    "content": "namespace Ticky.Internal.Services.Hosted;\n\npublic class SnoozeHostedService(IServiceScopeFactory serviceScopeFactory) : AbstractHostedService<SnoozeHostedService>(\n    serviceScopeFactory,\n    TimeSpan.FromSeconds(Constants.Limits.MINIMUM_SECOND_HOSTED_SERVICE_DELAY),\n    TimeSpan.FromMinutes(2))\n{\n    protected override async Task OnRun()\n    {\n        using var scope = ServiceScopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n        var logger = scope.ServiceProvider.GetRequiredService<ILogger<SnoozeHostedService>>()!;\n\n        var expiredSnoozes = await db\n            .Cards.Where(x => x.SnoozedUntil != null && x.SnoozedUntil <= DateTime.Now)\n            .ToListAsync();\n\n        foreach (var card in expiredSnoozes)\n        {\n            card.SnoozedUntil = null;\n        }\n\n        if (expiredSnoozes.Count != 0)\n        {\n            await db.SaveChangesAsync();\n            logger.LogInformation(\"{ExpiredSnoozesCount} cards unsnoozed.\", expiredSnoozes.Count);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/InformationService.cs",
    "content": "using System.Text.Json;\n\nnamespace Ticky.Internal.Services;\n\npublic class InformationService\n{\n    public IReadOnlyList<InformationDTO> Information { get; init; }\n\n    public InformationService()\n    {\n        if (!File.Exists(Constants.INFORMATION_PATH))\n            throw new FileNotFoundException(\n                \"Information file not found\",\n                Constants.INFORMATION_PATH\n            );\n\n        var information = JsonSerializer.Deserialize<List<InformationDTO>>(\n            File.ReadAllText(Constants.INFORMATION_PATH)\n        );\n\n        if (information is null)\n            throw new FormatException(\"Failed to parse information file\");\n\n        Information = information;\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/SearchService.cs",
    "content": "namespace Ticky.Internal.Services;\n\npublic class SearchService\n{\n    private readonly IDbContextFactory<DataContext> _dbContextFactory;\n\n    public SearchService(IDbContextFactory<DataContext> dbContextFactory)\n    {\n        _dbContextFactory = dbContextFactory;\n    }\n\n    public async Task<List<Card>> SearchAsync(\n        string? query,\n        User user,\n        CancellationToken cancellationToken = default\n    )\n    {\n        if (string.IsNullOrWhiteSpace(query))\n            return [];\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        return await db\n            .Cards.Include(x => x.Column)\n            .ThenInclude(x => x.Board)\n            .ThenInclude(x => x.Project)\n            .ThenInclude(x => x.Memberships)\n            .Include(x => x.Column)\n            .ThenInclude(x => x.Board)\n            .ThenInclude(x => x.Memberships)\n            .Where(x =>\n                x.Column.Board.Project.Memberships.Any(membership =>\n                    membership.UserId.Equals(user.Id)\n                ) || x.Column.Board.Memberships.Any(membership => membership.UserId.Equals(user.Id))\n            )\n            .Where(x =>\n                x.Name.Contains(query) || (x.Column.Board.Code + \"-\" + x.Number).Contains(query)\n            )\n            .Take(5)\n            .AsNoTracking()\n            .ToListAsync();\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Services/TrelloImportService.cs",
    "content": "using System.Drawing;\nusing Ticky.Base.Models;\n\nnamespace Ticky.Internal.Services;\n\npublic class TrelloImportService\n{\n    private readonly IDbContextFactory<DataContext> _dbContextFactory;\n\n    public TrelloImportService(IDbContextFactory<DataContext> dbContextFactory)\n    {\n        _dbContextFactory = dbContextFactory;\n    }\n\n    public async Task ImportTrelloBoardAsync(\n        ImportModel importModel,\n        int projectId,\n        int currentUserId\n    )\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n        var importDto = importModel.ImportDto!;\n\n        Dictionary<string, User> trelloIdToUser = new();\n\n        if (importModel.MemberIdentifiers is not null && importModel.MemberIdentifiers.Length != 0)\n        {\n            for (int i = 0; i < importModel.MemberIdentifiers.Length; i++)\n            {\n                var identifier = importModel.MemberIdentifiers[i];\n                var trelloId = importDto.Members[i].Id;\n\n                var user = await db.Users.FirstOrDefaultAsync(x =>\n                    identifier.Equals(x.Email) || identifier.Equals(x.DisplayName)\n                );\n\n                if (user is null)\n                    continue;\n\n                trelloIdToUser.Add(trelloId, user);\n            }\n        }\n\n        using var transaction = await db.Database.BeginTransactionAsync();\n\n        try\n        {\n            var board = new Board\n            {\n                Name = importDto.Name,\n                Description = importDto.Description,\n                ProjectId = projectId,\n                Code = importModel.Code\n            };\n\n            foreach (var label in importDto.Labels)\n            {\n                var (textColor, backgroundColor) = GetLabelColorsFromName(label.Color);\n\n                board.Labels.Add(\n                    new Label\n                    {\n                        Name = label.Name,\n                        BoardId = board.Id,\n                        TextColor = textColor,\n                        BackgroundColor = backgroundColor\n                    }\n                );\n            }\n\n            int columnIndex = 0;\n            int cardNumber = 1;\n\n            foreach (var list in importDto.Lists)\n            {\n                if (\n                    importModel.ArchivedCardsHandling.Equals(TrelloArchivedHandlingType.DontAdd)\n                    && list.Closed\n                )\n                    continue;\n\n                var column = new Column\n                {\n                    Name = list.Name,\n                    BoardId = board.Id,\n                    Index = columnIndex,\n                    MaxCards = list.SoftLimit ?? 0,\n                    Finished =\n                        importDto\n                            .Cards.Where(x => x.IdList.Equals(list.Id))\n                            .Any(x => x.DueComplete || x.DateCompleted.HasValue)\n                        || list.Name.Contains(\"Done\")\n                        || list.Name.Contains(\"🎉\")\n                };\n\n                int columnCardIndex = 0;\n                foreach (var card in importDto.Cards.Where(x => x.IdList.Equals(list.Id)))\n                {\n                    if (\n                        importModel.ArchivedCardsHandling.Equals(TrelloArchivedHandlingType.DontAdd)\n                        && card.Closed\n                    )\n                        continue;\n\n                    var newCard = new Card\n                    {\n                        Name = card.Name,\n                        Description = card.Description,\n                        Index = columnCardIndex,\n                        Deadline = card.Due,\n                        CreatedById = card.IdMemberCreator is not null\n                            ? (\n                                trelloIdToUser.GetValueOrDefault(card.IdMemberCreator)?.Id\n                                ?? currentUserId\n                            )\n                            : currentUserId,\n                        Number = cardNumber,\n                        ColumnId = column.Id,\n                    };\n\n                    if (card.DueReminder.HasValue && card.Due.HasValue)\n                    {\n                        var calculatedAt = card.Due.Value.AddMinutes(-card.DueReminder.Value);\n\n                        if (calculatedAt > DateTime.Now)\n                        {\n                            newCard.Reminders.Add(\n                                new Reminder\n                                {\n                                    At = card.Due.Value.AddMinutes(-card.DueReminder.Value),\n                                    CardId = newCard.Id\n                                }\n                            );\n                        }\n                        else\n                        {\n                            newCard.DeadlineProcessed = false;\n                        }\n                    }\n\n                    if (card.Due.HasValue && card.Due.Value < DateTime.Now)\n                    {\n                        newCard.DeadlineProcessed = true;\n                    }\n\n                    var appliedLabels = card\n                        .IdLabels.Select(x => importDto.Labels.First(l => l.Id.Equals(x)))\n                        .Select(x => board.Labels.First(y => y.Name.Equals(x.Name)));\n\n                    if (appliedLabels.Any())\n                        newCard.Labels.AddRange(appliedLabels);\n\n                    int subtaskIndex = 0;\n                    foreach (\n                        var checklists in importDto\n                            .Checklists.Where(x => x.IdCard.Equals(card.Id))\n                            .Select(x => x.CheckItems)\n                    )\n                    {\n                        foreach (var checklist in checklists)\n                        {\n                            newCard.Subtasks.Add(\n                                new()\n                                {\n                                    CardId = newCard.Id,\n                                    Text = checklist.Name,\n                                    Index = subtaskIndex,\n                                    Completed = checklist.State == \"complete\"\n                                }\n                            );\n                            subtaskIndex++;\n                        }\n                    }\n\n                    foreach (var cardMember in card.IdMembers)\n                    {\n                        if (trelloIdToUser.TryGetValue(cardMember, out var user))\n                            newCard.Assignees.Add(user);\n                    }\n\n                    column.Cards.Add(newCard);\n                    cardNumber++;\n                    columnCardIndex++;\n                }\n\n                board.Columns.Add(column);\n                columnIndex++;\n            }\n\n            db.Boards.Add(board);\n\n            await db.SaveChangesAsync();\n            await transaction.CommitAsync();\n        }\n        catch\n        {\n            await transaction.RollbackAsync();\n            throw;\n        }\n    }\n\n    private (Color textColor, Color backgroundColor) GetLabelColorsFromName(string colorName)\n    {\n        switch (colorName)\n        {\n            case \"purple\":\n                return (Color.FromArgb(53, 44, 99), Color.FromArgb(159, 143, 239));\n\n            case \"purple_dark\":\n                return (Color.White, Color.FromArgb(110, 93, 198));\n            case \"purple_light\":\n                return (Color.FromArgb(53, 44, 99), Color.FromArgb(223, 216, 253));\n\n            case \"red\":\n                return (Color.FromArgb(93, 31, 26), Color.FromArgb(248, 113, 104));\n\n            case \"red_dark\":\n                return (Color.White, Color.FromArgb(201, 55, 44));\n            case \"red_light\":\n                return (Color.FromArgb(93, 31, 26), Color.FromArgb(255, 213, 210));\n\n            case \"orange\":\n                return (Color.FromArgb(112, 46, 0), Color.FromArgb(254, 163, 98));\n\n            case \"orange_dark\":\n                return (Color.White, Color.FromArgb(194, 81, 0));\n            case \"orange_light\":\n                return (Color.FromArgb(112, 46, 0), Color.FromArgb(254, 222, 200));\n\n            case \"yellow\":\n                return (Color.FromArgb(83, 63, 4), Color.FromArgb(245, 205, 71));\n\n            case \"yellow_dark\":\n                return (Color.White, Color.FromArgb(148, 111, 0));\n            case \"yellow_light\":\n                return (Color.FromArgb(83, 63, 4), Color.FromArgb(248, 230, 160));\n\n            case \"green\":\n                return (Color.FromArgb(22, 75, 53), Color.FromArgb(75, 206, 151));\n\n            case \"green_dark\":\n                return (Color.White, Color.FromArgb(31, 132, 90));\n            case \"green_light\":\n                return (Color.FromArgb(22, 75, 53), Color.FromArgb(186, 243, 219));\n\n            case \"blue\":\n                return (Color.FromArgb(9, 50, 108), Color.FromArgb(87, 157, 255));\n\n            case \"blue_dark\":\n                return (Color.White, Color.FromArgb(12, 102, 228));\n            case \"blue_light\":\n                return (Color.FromArgb(9, 50, 108), Color.FromArgb(204, 224, 255));\n\n            case \"sky\":\n                return (Color.FromArgb(22, 69, 85), Color.FromArgb(108, 195, 224));\n\n            case \"sky_dark\":\n                return (Color.White, Color.FromArgb(34, 125, 155));\n            case \"sky_light\":\n                return (Color.FromArgb(22, 69, 85), Color.FromArgb(198, 237, 251));\n\n            case \"lime\":\n                return (Color.FromArgb(55, 71, 31), Color.FromArgb(148, 199, 72));\n\n            case \"lime_dark\":\n                return (Color.White, Color.FromArgb(91, 127, 36));\n            case \"lime_light\":\n                return (Color.FromArgb(55, 71, 31), Color.FromArgb(211, 241, 167));\n\n            case \"pink\":\n                return (Color.FromArgb(80, 37, 63), Color.FromArgb(231, 116, 187));\n\n            case \"pink_dark\":\n                return (Color.White, Color.FromArgb(174, 71, 135));\n            case \"pink_light\":\n                return (Color.FromArgb(80, 37, 63), Color.FromArgb(253, 208, 236));\n\n            case \"black\":\n                return (Color.FromArgb(9, 30, 66), Color.FromArgb(133, 144, 162));\n\n            case \"black_dark\":\n                return (Color.White, Color.FromArgb(98, 111, 134));\n            case \"black_light\":\n                return (Color.FromArgb(9, 30, 66), Color.FromArgb(220, 223, 228));\n        }\n\n        throw new Exception(\n            \"Unknown color. Please open a GitHub issue and include the application logs.\"\n        );\n    }\n}\n"
  },
  {
    "path": "Ticky.Internal/Ticky.Internal.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net9.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Devity.Extensions\" Version=\"2026.1.4.1450\" />\n    <PackageReference Include=\"Devity.Mailing\" Version=\"2025.8.13.2012\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Components\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.DataProtection.EntityFrameworkCore\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Identity.EntityFrameworkCore\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.SignalR.Client.Core\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.EntityFrameworkCore.Design\" Version=\"9.0.9\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.EntityFrameworkCore.Tools\" Version=\"9.0.9\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.Extensions.Hosting.Abstractions\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Pomelo.EntityFrameworkCore.MySql\" Version=\"9.0.0-preview.3.efcore.9.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Ticky.Base\\Ticky.Base.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Folder Include=\"Migrations\\\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Ticky.Units/CardTest.cs",
    "content": "namespace Ticky.Units;\n\npublic class CardTest\n{\n    private Card? _card;\n\n    [SetUp]\n    public void Setup()\n    {\n        _card = new()\n        {\n            Index = 0,\n            Number = 1,\n            ColumnId = 0,\n            Name = Constants.NAME,\n            CreatedById = 1,\n            RepeatInfo = new RepeatInfo\n            {\n                Type = RepeatType.Daily,\n                LastRepeat = DateTime.MinValue,\n                Time = TimeOnly.MinValue,\n                CardPlacement = CardPlacement.Top\n            },\n        };\n    }\n\n    [Test]\n    public void CalculateNextRepeat_Daily_SameDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 1, 15, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.Daily,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_Daily_NextDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 2, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.Daily,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_WeekDays_SameDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 9, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.WeekDays,\n            Selected = \"Mon,Tue,Wed\",\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_WeekDays_NextDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 6, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.WeekDays,\n            Selected = \"Mon,Tue,Wed\",\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_MonthDayNumber_SameDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 9, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.MonthDayNumber,\n            Selected = \"1\",\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_MonthDayNumber_NextDay()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 29, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.MonthDayNumber,\n            Selected = \"1,29\",\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthDay_TimeBefore()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 3, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthDay,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthWeek_TimeBefore()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 15, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthWeek,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthMonth_TimeBefore()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 3, 1, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthMonth,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthYear_TimeBefore()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2026, 1, 1, 9, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthYear,\n            Number = 1,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthDay_TimeAfter()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 3, 13, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthDay,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthWeek_TimeAfter()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 1, 15, 13, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthWeek,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthMonth_TimeAfter()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2025, 3, 1, 13, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthMonth,\n            Number = 2,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n\n    [Test]\n    public void CalculateNextRepeat_EveryXthYear_TimeAfter()\n    {\n        var lastRepeat = new DateTime(2025, 1, 1, 11, 0, 0);\n        var nextRepeat = new DateTime(2026, 1, 1, 13, 0, 0);\n\n        _card!.RepeatInfo = new RepeatInfo\n        {\n            Type = RepeatType.EveryXthYear,\n            Number = 1,\n            LastRepeat = lastRepeat,\n            Time = TimeOnly.FromDateTime(nextRepeat),\n            CardPlacement = CardPlacement.Top\n        };\n\n        Assert.That(_card!.CalculateNextRepeat(lastRepeat), Is.EqualTo(nextRepeat));\n    }\n}\n"
  },
  {
    "path": "Ticky.Units/Constants.cs",
    "content": "namespace Ticky.Units;\n\npublic static class Constants\n{\n    public const string NAME = \"Random Name\";\n}\n"
  },
  {
    "path": "Ticky.Units/GlobalUsings.cs",
    "content": "global using Moq;\nglobal using Ticky.Base.Entities;\nglobal using Ticky.Base.Entities.Owned;\nglobal using Ticky.Base.Enums;\nglobal using Ticky.Internal.Services;\n"
  },
  {
    "path": "Ticky.Units/Ticky.Units.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net9.0</TargetFramework>\n    <LangVersion>latest</LangVersion>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"coverlet.collector\" Version=\"6.0.2\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.12.0\" />\n    <PackageReference Include=\"Moq\" Version=\"4.20.72\" />\n    <PackageReference Include=\"NUnit\" Version=\"4.2.2\" />\n    <PackageReference Include=\"NUnit.Analyzers\" Version=\"4.4.0\" />\n    <PackageReference Include=\"NUnit3TestAdapter\" Version=\"4.6.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Ticky.Base\\Ticky.Base.csproj\" />\n    <ProjectReference Include=\"..\\Ticky.Internal\\Ticky.Internal.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Using Include=\"NUnit.Framework\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Ticky.Web/Components/App.razor",
    "content": "<!DOCTYPE html>\n<html class=\"text-app-text\" lang=\"en\" data-theme=\"\">\n\n<head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"description\" content=\"Ticky, the kanban board app designed to make your life simpler and your tasks feel lighter. With its intuitive visual layout, you can effortlessly move your projects from to-do to done, making productivity feel like a breeze. Get ready to tick off your goals with a smile!\">\n    <link rel=\"preload\" href=\"fonts/o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5a7duw.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />\n    <base href=\"/\" />\n    <link rel=\"stylesheet\" href=\"@Assets[\"css/app.css\"]\" />\n    <link rel=\"icon\" type=\"image/png\" href=\"./images/favicon.ico\" />\n    <link rel=\"stylesheet\" href=\"@Assets[\"fonts/Noto-Sans.css\"]\">\n    <link rel=\"stylesheet\" href=\"@Assets[\"font-awesome/css/fontawesome.min.css\"]\">\n    <link rel=\"stylesheet\" href=\"@Assets[\"font-awesome/css/solid.min.css\"]\">\n    <link rel=\"stylesheet\" href=\"@Assets[\"font-awesome/css/regular.min.css\"]\">\n    <link href=\"Ticky.Web.styles.css\" rel=\"stylesheet\" />\n    <script src=\"js/main.js\"></script>\n    <script src=\"@Assets[\"js/sortable/Sortable.min.js\"]\"></script>\n    <script type=\"module\" src=\"../Components/Elements/Sortable/SortableList.razor.js\"></script>\n    <ImportMap />\n    <HeadOutlet @rendermode=\"InteractiveServer\" />\n    <title>@Constants.APP_NAME</title>\n</head>\n\n<body class=\"flex flex-col bg-app-bg transition-colors\">\n    <Routes @rendermode=\"InteractiveServer\" />\n    <script src=\"_framework/blazor.web.js\"></script>\n    <script src=\"js/screenHeight.js\" type=\"text/javascript\"></script>\n    <script src=\"js/downloadFile.js\" type=\"text/javascript\"></script>\n    <script src=\"js/focusTrap.js\" type=\"text/javascript\"></script>\n    <script src=\"js/darkTheme.js\" type=\"text/javascript\"></script>\n    <script src=\"js/confetti.browser.min.js\" type=\"text/javascript\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AbstractModal.razor",
    "content": "@implements IDisposable\n\n@code {\n    protected object? FocusElement { get; set; }\n\n    protected Modal? Modal;\n\n    public virtual async void Open()\n    {\n        if (Modal is null)\n            return;\n\n        OnOpen();\n        await Modal.Show();\n\n        ElementReference? element = null;\n\n        if (FocusElement is InputText inputText)\n            element = inputText.Element.GetValueOrDefault();\n        else if (FocusElement is InputTextArea inputTextArea)\n            element = inputTextArea.Element.GetValueOrDefault();\n        else if (FocusElement is ElementReference elementReference)\n            element = elementReference;\n\n        if(element.HasValue)\n            await element.Value.FocusAsync();\n    }\n\n    protected virtual void OnOpen()\n    {\n        \n    }\n\n    public virtual void Dispose()\n    {\n\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddLabelModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=Modal Title=\"Add label\" OnSubmitAttempted=\"AddLabel\">\n    @if(_board is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" EditContext=\"_editContext\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.Text\" />\n                <input type=\"text\" class=\"form-control\" value=\"@_labelModel.Text\" @oninput=\"OnTextUpdated\" @ref=\"FocusElement\" />\n                <ValidationMessage For=\"() => _labelModel.Text\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.TextColor\" />\n                <input type=\"color\" value=\"@(_labelModel.TextColor.HasValue ? ColorTranslator.ToHtml(_labelModel.TextColor.Value) : string.Empty)\" @onchange=\"OnTextColorUpdated\" />\n                <ValidationMessage For=\"() => _labelModel.TextColor\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.BackgroundColor\" />\n                <input type=\"color\" value=\"@(_labelModel.BackgroundColor.HasValue ? ColorTranslator.ToHtml(_labelModel.BackgroundColor.Value) : string.Empty)\" @onchange=\"OnBackgroundColorUpdated\" />\n                <ValidationMessage For=\"() => _labelModel.BackgroundColor\" />\n            </div>\n\n            <div class=\"form-group\">\n                <label>Preview:</label>\n                <LabelView Label=\"_showcaseLabel\"/>\n            </div>\n        </EditForm>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Board? _board;\n    private LabelModel _labelModel = new();\n    private Label? _showcaseLabel;\n    private EditContext? _editContext;\n\n    public void Open(Board board) {\n        _board = board;\n        _labelModel = new();\n        _showcaseLabel = new()\n            {\n                BoardId = board.Id,\n                Name = \"Example\",\n                BackgroundColor = Color.AliceBlue,\n                TextColor = Color.Black\n            };\n        _editContext = new EditContext(_labelModel);\n\n        base.Open();\n    }\n\n    private void OnTextUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        if(string.IsNullOrWhiteSpace(str))\n        {\n            _showcaseLabel.Name = \"Example\";\n            return;\n        }\n\n        _showcaseLabel.Name = str;\n        _labelModel.Text = str;\n    }\n\n    private void OnTextColorUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        _showcaseLabel.TextColor = ColorTranslator.FromHtml(str);\n        _labelModel.TextColor = _showcaseLabel.TextColor;\n    }\n\n    private void OnBackgroundColorUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        _showcaseLabel.BackgroundColor = ColorTranslator.FromHtml(str);\n        _labelModel.BackgroundColor = _showcaseLabel.BackgroundColor;\n    }\n\n    public async Task AddLabel() \n    {\n        if(_board is null || _editContext is null || !_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var board = await db.Boards\n            .Include(x => x.Labels)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if(board is null)\n            return;\n\n        board.Labels.Add(new Label\n        {\n            BoardId = board.Id,\n            Name = _labelModel.Text,\n            TextColor = _labelModel.TextColor!.Value,\n            BackgroundColor = _labelModel.BackgroundColor!.Value\n        });\n\n        await db.SaveChangesAsync();\n\n        _board = board;\n        StateHasChanged();\n        await OnSubmit.InvokeAsync();\n        Modal?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddOrEditRepeatModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Repeat card [BETA]\">\n    @if(_card is null || _columns is null) \n    {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_repeatModel\" OnValidSubmit=\"OnValidSubmit\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _repeatModel.Type\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_repeatModel.Type\">\n                    @foreach (Enum enumValue in Enum.GetValues(typeof(RepeatType)))\n                    {\n                        if (_repeatModel.Type.Equals(enumValue))\n                        {\n                            <option selected value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                        else\n                        {\n                            <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _repeatModel.Type\" />\n            </div>\n\n            @if(_repeatModel.Type == RepeatType.WeekDays)\n            {\n                <div class=\"form-group\">\n                    <Name For=\"() => _repeatModel.SelectedWeekDays\" />\n                    <InputText class=\"form-control\" @bind-Value=\"_repeatModel.SelectedWeekDays\" placeholder=\"Mon,Tue,Sun\" />\n                    <ValidationMessage For=\"() => _repeatModel.SelectedWeekDays\" />\n                </div>\n            }\n            else if(_repeatModel.Type == RepeatType.MonthDayNumber)\n            {\n                <div class=\"form-group\">\n                    <Name For=\"() => _repeatModel.SelectedMonthDays\" />\n                    <InputText class=\"form-control\" @bind-Value=\"_repeatModel.SelectedMonthDays\" placeholder=\"1,15,31\" />\n                    <ValidationMessage For=\"() => _repeatModel.SelectedMonthDays\" />\n                </div>\n            }\n            else if (_repeatModel.Type >= RepeatType.EveryXthDay && _repeatModel.Type <= RepeatType.EveryXthYear)\n            {\n                <div class=\"form-group\">\n                    <Name For=\"() => _repeatModel.Number\" />\n                    <InputNumber class=\"form-control\" @bind-Value=\"_repeatModel.Number\" />\n                    <ValidationMessage For=\"() => _repeatModel.Number\" />\n                </div>\n            }\n\n            <div class=\"form-group\">\n                <Name For=\"() => _repeatModel.StartDate\" />\n                <InputDate @bind-Value=\"_repeatModel.StartDate\" />\n                <ValidationMessage For=\"() => _repeatModel.StartDate\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _repeatModel.Time\" />\n                <TimeSelect @bind-Value=\"_repeatModel.Time\" />\n                <ValidationMessage For=\"() => _repeatModel.Time\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _repeatModel.CardPlacement\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_repeatModel.CardPlacement\">\n                    @foreach (Enum enumValue in Enum.GetValues(typeof(CardPlacement)))\n                    {\n                        if (_repeatModel.CardPlacement.Equals(enumValue))\n                        {\n                            <option selected value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                        else\n                        {\n                            <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _repeatModel.CardPlacement\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _repeatModel.TargetColumnId\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_repeatModel.TargetColumnId\">\n                    <option value=\"0\"></option>\n                    @foreach (var column in _columns.OrderBy(x => x.Index))\n                    {\n                        if (_repeatModel.TargetColumnId.Equals(column.Id))\n                        {\n                            <option selected value=\"@column.Id\">@column.Name</option>\n                        }\n                        else\n                        {\n                            <option value=\"@column.Id\">@column.Name</option>\n                        }\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _repeatModel.TargetColumnId\" />\n            </div>\n\n            <button type=\"submit\">Set</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private RepeatCardModel _repeatModel = new();\n    private List<Column>? _columns;\n\n    public void Open(ElementReference? triggerElement, Card card, List<Column> columns) \n    {\n        _card = card;\n\n        _repeatModel = new()\n            {\n                Time = DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute).ToString(\"HH:mm\")\n            };\n\n        if(card.RepeatInfo is not null) \n        {\n            _repeatModel = new()\n                {\n                    Type = card.RepeatInfo.Type,\n                    StartDate = DateOnly.FromDateTime(card.RepeatInfo.LastRepeat),\n                    Time = card.RepeatInfo.Time.ToString(\"HH:mm\"),\n                    Number = card.RepeatInfo.Number,\n                    CardPlacement = card.RepeatInfo.CardPlacement,\n                    TargetColumnId = card.RepeatInfo.TargetColumnId\n                };\n\n            _repeatModel.SetRelevantSelectedValue(card.RepeatInfo.Selected);\n        }\n\n        _columns = columns;\n\n        _modalRef?.Open(triggerElement);\n        StateHasChanged();\n    }\n\n    public async Task OnValidSubmit() \n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var card = await db.Cards\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var time = DateTime.ParseExact(_repeatModel.Time, \"HH:mm\", null);\n        var timeOnly = TimeOnly.FromDateTime(time);\n\n        card.RepeatInfo = new()\n        {\n            Type = _repeatModel.Type,\n            LastRepeat = _repeatModel.StartDate.ToDateTime(timeOnly),\n            Time = timeOnly,\n            Number = _repeatModel.Number,\n            Selected = _repeatModel.GetRelevantSelectedValue(),\n            CardPlacement = _repeatModel.CardPlacement,\n            TargetColumnId = _repeatModel.TargetColumnId\n        };\n\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>set up card repeat</b> for this card for <b>{card.RepeatInfo.Type.GetDisplayName()}</b>\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddReminderModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Add reminder\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_reminderModel\" OnValidSubmit=\"AddReminder\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _reminderModel.At\" />\n                <InputDate class=\"form-control\" @bind-Value=\"_reminderModel.At\" min=\"@DateTime.Today.ToHtmlDateString()\" />\n                <ValidationMessage For=\"() => _reminderModel.At\" />\n            </div>\n            <div class=\"form-group\">\n                <Name For=\"() => _reminderModel.Time\" />\n                <TimeSelect @bind-Value=\"_reminderModel.Time\" />\n                <ValidationMessage For=\"() => _reminderModel.Time\" />\n            </div>\n\n            <button type=\"submit\">Add</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private ReminderModel _reminderModel = new();\n\n    public void Open(ElementReference? triggerElement, Card card) {\n        _card = card;\n        _reminderModel = new();\n        _modalRef?.Open(triggerElement);\n        StateHasChanged();\n    }\n\n    public async Task AddReminder() \n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Reminders)\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var time = DateTime.ParseExact(_reminderModel.Time, \"HH:mm\", null);\n\n        var newReminder = new Reminder\n            {\n                CardId = card.Id,\n                At = new DateTime(_reminderModel.At.Year, _reminderModel.At.Month, _reminderModel.At.Day, time.Hour, time.Minute, 0)\n            };\n\n        card.Reminders.Add(newReminder);\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>added</b> a reminder for <b>{newReminder.At.ToReadableStringWithTime()}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddSubtaskModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Add subtask\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_subtaskModel\" OnValidSubmit=\"AddSubtask\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _subtaskModel.Text\" />\n                <InputText class=\"form-control\" @bind-Value=\"_subtaskModel.Text\" />\n                <ValidationMessage For=\"() => _subtaskModel.Text\" />\n            </div>\n\n            <button type=\"submit\">Add</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private SubtaskModel _subtaskModel = new();\n\n    public void Open(ElementReference? triggerElement, Card card) {\n        _card = card;\n        _subtaskModel = new();\n        StateHasChanged();\n        _modalRef?.Open(triggerElement);\n    }\n\n    public async Task AddSubtask() \n    {\n        if(_card is null || _modalRef is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Subtasks)\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        card.Subtasks.Add(new Subtask\n        {\n            CardId = card.Id,\n            Text = _subtaskModel.Text,\n            Index = IndexHelper.GetNextIndex(card.Subtasks)\n            });\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>added</b> subtask <b>{_subtaskModel.Text}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        _subtaskModel = new();\n        await UpdateCard.InvokeAsync();\n        await _modalRef.TrapFocus();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddTimeRecordModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Add time record\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_timeRecordModel\" OnValidSubmit=\"AddTimeRecord\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _timeRecordModel.Time\" />\n                <InputText class=\"form-control\" @bind-Value=\"_timeRecordModel.Time\" />\n                <ValidationMessage For=\"() => _timeRecordModel.Time\" />\n            </div>\n\n            <button type=\"submit\">Add</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private TimeRecordModel _timeRecordModel = new();\n\n    public void Open(string triggerElementId, Card card) \n    {\n        _card = card;\n        _timeRecordModel = new();\n        _modalRef?.Open(triggerElementId);\n        StateHasChanged();\n    }\n\n    public async Task AddTimeRecord() \n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var card = await db.Cards\n            .Include(x => x.TimeRecords)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var timeSpan = _timeRecordModel.Time.ConvertToTimeSpan();\n\n        var timeRecord = new TimeRecord\n            {\n                CardId = card.Id,\n                UserId = _user.Id,\n                StartedAt = DateTime.Now.Subtract(timeSpan),\n                EndedAt = DateTime.Now\n            };\n\n        card.TimeRecords.Add(timeRecord);\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>added</b> a time record for <b>{(timeRecord.EndedAt.Value-timeRecord.StartedAt).ToElapsedString()}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AddUserModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject UserManager<User> _userManager\n@inject AvatarService _avatarService\n\n<Modal @ref=Modal Title=\"Add user\" OnSubmitAttempted=\"AddUser\">\n    <EditForm class=\"form p-2\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator />\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.DisplayName\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.DisplayName\" @ref=FocusElement />\n            <ValidationMessage For=\"() => _userModel.DisplayName\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.Email\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.Email\" />\n            <ValidationMessage For=\"() => _userModel.Email\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.Password\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.Password\" />\n            <ValidationMessage For=\"() => _userModel.Password\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.ConfirmPassword\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.ConfirmPassword\" />\n            <ValidationMessage For=\"() => _userModel.ConfirmPassword\" />\n        </div>\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private UserModel _userModel = new();\n    private EditContext? _editContext;\n    private ValidationMessageStore? _validationMessageStore;\n\n    public override void Open() \n    {\n        _userModel = new();\n        _editContext = new EditContext(_userModel);\n        _editContext.OnValidationRequested += (sender, args) =>\n        {\n            _validationMessageStore?.Clear();\n        };\n        _validationMessageStore = new(_editContext);\n\n        base.Open();\n    }\n\n    public async Task AddUser() \n    {\n        if(_editContext is null || !_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var user = new User\n        {\n            DisplayName = _userModel.DisplayName,\n            Email = _userModel.Email,\n            UserName = _userModel.Email,\n            NeedsNewCredentials = true,\n            ProfilePictureFileName = await _avatarService.FetchAvatarAsync(_userModel.DisplayName)\n        };\n\n        var result = await _userManager.CreateAsync(user, _userModel.Password);\n\n        if(!result.Succeeded)\n        {\n            foreach (var error in result.Errors)\n                _validationMessageStore?.Add(() => _userModel.Email, error.Description);\n\n            _editContext?.NotifyValidationStateChanged();\n            return;\n        }\n\n        StateHasChanged();\n        await OnSubmit.InvokeAsync();\n        Modal?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/AssigneesModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Assignees\">\n    @if(_assignable is null) \n    {\n        <Spinner/>\n    } else {\n        <div class=\"flex w-full flex-col items-center\">\n            @foreach(var member in _members) \n            {\n                <div class=\"flex w-72 cursor-pointer flex-row items-center gap-5 rounded px-2 py-1 text-sm transition-all ease-in-out select-none hover:bg-dropdown-option\" @onclick=\"() => SwitchMember(member)\">\n                    <div class=\"avatar mr-auto\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@member.ProfilePictureFileName');\"></div>\n                    <label class=\"cursor-pointer\">@member.DisplayName</label>\n                    <i class='fa fa-check icon ml-auto @(!_assignable.Assignees.Any(x => x.Id.Equals(member.Id)) ? \"opacity-0\" : string.Empty)'></i>\n                </div>\n            }\n        </div>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private IAssignable? _assignable;\n\n    private List<User> _members = [];\n\n    public void Open(ElementReference? triggerElement, IAssignable assignable, List<User> members) \n    {\n        _assignable = assignable;\n        _members = members;\n        StateHasChanged();\n        _modalRef?.Open(triggerElement);\n    }\n\n    public async Task SwitchMember(User member) \n    {\n        if(_assignable is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        if (_assignable is Card card)\n        {\n            var targetCard = await db.Cards\n                .Include(x => x.Assignees)\n                .Include(x => x.Activities)\n                .FirstOrDefaultAsync(x => x.Id.Equals(card.Id));\n\n            if (targetCard is null)\n                return;\n\n            var targetUser = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(member.Id));\n\n            if (targetUser is null)\n                return;\n\n            if (targetCard.Assignees.Contains(targetUser)) \n            {\n                targetCard.Assignees.Remove(targetUser);\n                targetCard.Activities.Add(new Activity\n                {\n                    Text = $\"<b>removed</b> the user <b>{targetUser.DisplayName}</b> from the assignees\",\n                    UserId = _user.Id,\n                    CardId = targetCard.Id,\n                });\n            }\n            else \n            {\n                targetCard.Assignees.Add(targetUser);\n                targetCard.Activities.Add(new Activity\n                {\n                    Text = $\"<b>added</b> the user <b>{targetUser.DisplayName}</b> as an assignee\",\n                    UserId = _user.Id,\n                    CardId = targetCard.Id,\n                });\n            }\n\n            await db.SaveChangesAsync();\n\n            _assignable = targetCard;\n            StateHasChanged();\n            await UpdateCard.InvokeAsync();\n        } else if (_assignable is Subtask subtask)\n        {\n            var targetSubtask = await db.Subtasks\n                .Include(x => x.Assignees)\n                .Include(x => x.Card)\n                    .ThenInclude(x => x.Activities)\n                .FirstOrDefaultAsync(x => x.Id.Equals(subtask.Id));\n\n            if (targetSubtask is null)\n                return;\n\n            var targetUser = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(member.Id));\n\n            if (targetUser is null)\n                return;\n\n            if (targetSubtask.Assignees.Contains(targetUser)) \n            {\n                targetSubtask.Assignees.Remove(targetUser);\n                targetSubtask.Card.Activities.Add(new Activity\n                {\n                    Text = $\"<b>removed</b> the user <b>{targetUser.DisplayName}</b> from the subtask assignees\",\n                    UserId = _user.Id,\n                    CardId = targetSubtask.CardId,\n                });\n            }\n            else \n            {\n                targetSubtask.Assignees.Add(targetUser);\n                targetSubtask.Card.Activities.Add(new Activity\n                {\n                    Text = $\"<b>added</b> the user <b>{targetUser.DisplayName}</b> as a subtask assignee\",\n                    UserId = _user.Id,\n                    CardId = targetSubtask.CardId,\n                });\n            }\n\n            await db.SaveChangesAsync();\n\n            _assignable = targetSubtask;\n            StateHasChanged();\n            await UpdateCard.InvokeAsync();\n        }\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/CloneBoardModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n@inherits AbstractModal\n\n<Modal @ref=\"Modal\" Title=\"Clone board\" OnSubmitAttempted=\"OnSubmitAttempted\">\n\t<EditForm class=\"form\" EditContext=\"_editContext\">\n\t\t<DataAnnotationsValidator />\n\n\t\t<div class=\"form-group\">\n\t\t\t<Name For=\"() => _model.TargetProjectId\" />\n\t\t\t<InputSelect class=\"form-control\" @bind-Value=\"_model.TargetProjectId\">\n\t\t\t\t<option value=\"\">Select project...</option>\n\t\t\t\t@foreach (var project in _projects)\n\t\t\t\t{\n\t\t\t\t\t<option value=\"@project.Id\">@project.Name</option>\n\t\t\t\t}\n\t\t\t</InputSelect>\n\t\t\t<ValidationMessage For=\"() => _model.TargetProjectId\" />\n\t\t</div>\n\n\t\t<div class=\"form-group\">\n\t\t\t<Name For=\"() => _model.Code\" />\n\t\t\t<InputText class=\"form-control\" @bind-Value=\"_model.Code\" />\n\t\t\t<ValidationMessage For=\"() => _model.Code\" />\n\t\t</div>\n\t</EditForm>\n</Modal>\n\n@code {\n\t[CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n\tprivate User _user { get; set; } = default!;\n\n\t[CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n\tprivate MainLayout _mainLayout { get; set; } = default!;\n\n\t[Parameter]\n\tpublic EventCallback OnCloned { get; set; }\n\n\tprivate Board? _sourceBoard;\n\tprivate List<Project> _projects = [];\n\n\tprivate CloneBoardModel _model = new();\n\tprivate EditContext? _editContext;\n\n\tpublic async Task Open(Board sourceBoard)\n\t{\n\t\t_sourceBoard = sourceBoard;\n\n\t\tusing var db = _dbContextFactory.CreateDbContext();\n\n\t\t_projects = await db.Projects\n\t\t\t.Include(x => x.Memberships)\n\t\t\t.AsNoTracking()\n\t\t\t.Where(x => x.Memberships.Any(m => m.UserId.Equals(_user.Id)))\n\t\t\t.ToListAsync();\n\n\t\t_model = new CloneBoardModel\n\t\t{\n\t\t\tTargetProjectId = sourceBoard.ProjectId,\n\t\t\tCode = sourceBoard.Code,\n\t\t};\n\t\t_editContext = new(_model);\n\n\t\tbase.Open();\n\t}\n\n\tprivate async Task OnSubmitAttempted()\n\t{\n\t\tif (Modal is null || _editContext is null)\n\t\t\treturn;\n\n\t\tif (!_editContext.Validate())\n\t\t\treturn;\n\n\t\tawait OnValidSubmit();\n\t}\n\n\tprivate async Task OnValidSubmit()\n\t{\n\t\tif (_sourceBoard is null || Modal is null)\n\t\t\treturn;\n\n\t\ttry\n\t\t{\n\t\t\tusing var db = _dbContextFactory.CreateDbContext();\n\n\t\t\tvar board = await db.Boards\n\t\t\t\t.Include(x => x.Columns)\n\t\t\t\t\t.ThenInclude(c => c.Cards)\n\t\t\t\t\t\t.ThenInclude(c => c.Labels)\n\t\t\t\t.Include(x => x.Columns)\n\t\t\t\t\t.ThenInclude(c => c.Cards)\n\t\t\t\t\t\t.ThenInclude(c => c.Assignees)\n\t\t\t\t.Include(x => x.Columns)\n\t\t\t\t\t.ThenInclude(c => c.Cards)\n\t\t\t\t\t\t.ThenInclude(c => c.Subtasks)\n\t\t\t\t.Include(x => x.Columns)\n\t\t\t\t\t.ThenInclude(c => c.Cards)\n\t\t\t\t\t\t.ThenInclude(c => c.Reminders)\n\t\t\t\t.Include(x => x.Labels)\n\t\t\t\t.Include(x => x.Memberships)\n\t\t\t\t.FirstOrDefaultAsync(x => x.Id.Equals(_sourceBoard.Id));\n\n\t\t\tif (board is null)\n\t\t\t{\n\t\t\t\t_mainLayout.RunNotification(new(\"Source board not found.\", NotificationType.Fail));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar newBoard = new Board\n\t\t\t{\n\t\t\t\tName = $\"Copy of {board.Name}\",\n\t\t\t\tDescription = board.Description,\n\t\t\t\tCode = _model.Code,\n\t\t\t\tProjectId = _model.TargetProjectId!.Value,\n\t\t\t\tDisableSortingAnimations = board.DisableSortingAnimations\n\t\t\t};\n\n\t\t\tforeach (var membership in board.Memberships)\n\t\t\t{\n\t\t\t\tvar user = await db.Users.FindAsync(membership.UserId);\n\n\t\t\t\tif (user is not null)\n\t\t\t\t{\n\t\t\t\t\tnewBoard.Memberships.Add(new BoardMembership\n\t\t\t\t\t{\n\t\t\t\t\t\tBoardId = newBoard.Id,\n\t\t\t\t\t\tUserId = user.Id,\n\t\t\t\t\t\tAddedAt = membership.AddedAt,\n\t\t\t\t\t\tIsAdmin = membership.IsAdmin,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar labelMap = new Dictionary<int, Label>();\n\n\t\t\tforeach (var label in board.Labels.OrderBy(x => x.Id))\n\t\t\t{\n\t\t\t\tvar newLabel = new Label\n\t\t\t\t{\n\t\t\t\t\tName = label.Name,\n\t\t\t\t\tTextColor = label.TextColor,\n\t\t\t\t\tBackgroundColor = label.BackgroundColor,\n\t\t\t\t\tBoardId = newBoard.Id\n\t\t\t\t};\n\t\t\t\tnewBoard.Labels.Add(newLabel);\n\t\t\t\tlabelMap[label.Id] = newLabel;\n\t\t\t}\n\n\t\t\tDictionary<Card, Card> cardMap = [];\n\n\t\t\tforeach (var column in board.Columns.OrderBy(x => x.Index))\n\t\t\t{\n\t\t\t\tvar newColumn = new Column\n\t\t\t\t{\n\t\t\t\t\tName = column.Name,\n\t\t\t\t\tIndex = column.Index,\n\t\t\t\t\tMaxCards = column.MaxCards,\n\t\t\t\t\tFinished = column.Finished,\n\t\t\t\t\tCollapsed = column.Collapsed,\n\t\t\t\t\tNewCardPlacement = column.NewCardPlacement,\n\t\t\t\t\tOrderRule = column.OrderRule,\n\t\t\t\t\tBoardId = newBoard.Id\n\t\t\t\t};\n\n\t\t\t\tforeach (var card in column.Cards.OrderBy(x => x.Index))\n\t\t\t\t{\n\t\t\t\t\tvar newCard = new Card\n\t\t\t\t\t{\n\t\t\t\t\t\tName = card.Name,\n\t\t\t\t\t\tDescription = card.Description,\n\t\t\t\t\t\tNumber = card.Number,\n\t\t\t\t\t\tIndex = card.Index,\n\t\t\t\t\t\tFlagged = card.Flagged,\n\t\t\t\t\t\tDeadline = card.Deadline,\n\t\t\t\t\t\tDeadlineProcessed = card.DeadlineProcessed,\n\t\t\t\t\t\tPriority = card.Priority,\n\t\t\t\t\t\tCreatedById = card.CreatedById,\n\t\t\t\t\t\tCreatedAt = DateTime.Now,\n\t\t\t\t\t\tColumnId = newColumn.Id,\n\t\t\t\t\t\tSnoozedUntil = card.SnoozedUntil\n\t\t\t\t\t};\n\n\t\t\t\t\tforeach (var cardLabel in card.Labels)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (labelMap.TryGetValue(cardLabel.Id, out var mapped))\n\t\t\t\t\t\t\tnewCard.Labels.Add(mapped);\n\t\t\t\t\t}\n\n\t\t\t\t\tforeach (var assignee in card.Assignees)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar user = await db.Users.FindAsync(assignee.Id);\n\n\t\t\t\t\t\tif (user is not null)\n\t\t\t\t\t\t\tnewCard.Assignees.Add(user);\n\t\t\t\t\t}\n\n\t\t\t\t\tforeach (var subtask in card.Subtasks.OrderBy(x => x.Index))\n\t\t\t\t\t{\n\t\t\t\t\t\tnewCard.Subtasks.Add(new Subtask\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tText = subtask.Text,\n\t\t\t\t\t\t\tCompleted = subtask.Completed,\n\t\t\t\t\t\t\tIndex = subtask.Index,\n\t\t\t\t\t\t\tCardId = newCard.Id\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tforeach (var reminder in card.Reminders)\n\t\t\t\t\t{\n\t\t\t\t\t\tnewCard.Reminders.Add(new Reminder\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tAt = reminder.At,\n\t\t\t\t\t\t\tCardId = newCard.Id\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tnewColumn.Cards.Add(newCard);\n\n\t\t\t\t\tcardMap.Add(card, newCard);\n\t\t\t\t}\n\n\t\t\t\tnewBoard.Columns.Add(newColumn);\n\t\t\t}\n\n\t\t\tdb.Boards.Add(newBoard);\n\n\t\t\tawait db.SaveChangesAsync();\n\n\t\t\tforeach(var createdCardPair in cardMap)\n\t\t\t{\n\t\t\t\tvar sourceCardRepeatInfo = createdCardPair.Key.RepeatInfo;\n\n\t\t\t\tif(sourceCardRepeatInfo is null)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tcreatedCardPair.Value.RepeatInfo = new RepeatInfo\n\t\t\t\t{\n\t\t\t\t\tCardPlacement = sourceCardRepeatInfo.CardPlacement,\n\t\t\t\t\tLastRepeat = sourceCardRepeatInfo.LastRepeat,\n\t\t\t\t\tNumber = sourceCardRepeatInfo.Number,\n                    Time = sourceCardRepeatInfo.Time,\n                    Type = sourceCardRepeatInfo.Type,\n                    Selected = sourceCardRepeatInfo.Selected,\n\t\t\t\t\tTargetColumnId = newBoard.Columns.First(newColumn => newColumn.Index.Equals(board.Columns.First(x => x.Id.Equals(sourceCardRepeatInfo.TargetColumnId)).Index)).Id\n                };\n\t\t\t}\n\n\t\t\tawait db.SaveChangesAsync();\n\n\t\t\t_mainLayout.RunNotification(new(\"Board cloned successfully.\", NotificationType.Success));\n\t\t\tawait OnCloned.InvokeAsync();\n\t\t\tawait Modal.Close();\n\t\t}\n\t\tcatch (Exception ex)\n\t\t{\n\t\t\t_mainLayout.RunNotification(new($\"Failed to clone board: {ex.Message}\", NotificationType.Fail));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/CreateBoardModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"New board\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    <EditForm class=\"form\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator />\n\n        <div class=\"form-group\">\n            <Name For=\"() => _board.Name\" />\n            <InputText class=\"form-control\" @bind-Value=\"_board.Name\" @ref=\"FocusElement\"/>\n            <ValidationMessage For=\"() => _board.Name\" />\n        </div>\n        \n        <div class=\"form-group\">\n            <Name For=\"() => _board.Description\" />\n            <InputText class=\"form-control\" @bind-Value=\"_board.Description\" />\n            <ValidationMessage For=\"() => _board.Description\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _board.Code\" />\n            <InputText class=\"form-control\" @bind-Value=\"_board.Code\" />\n            <ValidationMessage For=\"() => _board.Code\" />\n        </div>\n\n        <div class=\"form-group text-xs font-normal\">\n            Got an existing board? <a class=\"auth-link\" @onclick=\"GoToImport\">Import</a>\n        </div>\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    [Parameter]\n    public required ImportModal ImportModal { get; set; }\n\n    public int _projectId { get; set; }\n\n    private Board _board = new()\n    {\n        Name = string.Empty,\n        Code = string.Empty,\n        Description = string.Empty,\n        ProjectId = 0\n    };\n\n    private EditContext? _editContext;\n\n    public void Open(int projectId)\n    {\n        _projectId = projectId;\n        _board.ProjectId = projectId;\n\n        _board = new()\n            {\n                Name = string.Empty,\n                Code = string.Empty,\n                Description = string.Empty,\n                ProjectId = 0\n            };\n        _editContext = new EditContext(_board);\n\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if (Modal is null || _editContext is null || _board is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var project = await db.Projects.FirstOrDefaultAsync(x => x.Id.Equals(_projectId));\n\n        if (project is not null)\n        {\n            var defaultLabels = new List<Label>\n            {\n                new Label { Name = \"Bug\", TextColor = Color.White, BackgroundColor = Color.FromArgb(220, 38, 38), BoardId = _board.Id },\n                new Label { Name = \"Feature\", TextColor = Color.White, BackgroundColor = Color.FromArgb(16, 185, 129), BoardId = _board.Id },\n                new Label { Name = \"Enhancement\", TextColor = Color.White, BackgroundColor = Color.FromArgb(59, 130, 246), BoardId = _board.Id }\n            };\n\n            _board.Labels.AddRange(defaultLabels);\n\n            project.Boards.Add(_board);\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async Task GoToImport()\n    {\n        if (Modal is null)\n            return;\n\n        await Modal.Close();\n        ImportModal.Open(_projectId);\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/CreateColumnModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"New column\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    <EditForm class=\"form\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator />\n        \n        <div class=\"form-group\">\n            <Name For=\"() => _column.Name\" />\n            <InputText class=\"form-control\" @bind-Value=\"_column.Name\" @ref=\"FocusElement\" />\n            <ValidationMessage For=\"() => _column.Name\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _column.MaxCards\" />\n            <InputNumber class=\"form-control\" @bind-Value=\"_column.MaxCards\" />\n            <ValidationMessage For=\"() => _column.MaxCards\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _column.Finished\" />\n            <InputCheckbox class=\"switch\" @bind-Value=\"_column.Finished\" />\n            <ValidationMessage For=\"() => _column.Finished\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _column.NewCardPlacement\" />\n            <InputSelect class=\"form-control\" @bind-Value=\"_column.NewCardPlacement\">\n                @foreach (Enum enumValue in Enum.GetValues<CardPlacement>())\n                {\n                    <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                }\n            </InputSelect>\n            <ValidationMessage For=\"() => _column.NewCardPlacement\" />\n        </div>\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    public int _boardId { get; set; }\n\n    private Column _column = new()\n    {\n        Name = string.Empty,\n        BoardId = 0,\n        Index = 0\n    };\n\n    private EditContext? _editContext;\n\n    public void Open(int boardId)\n    {\n        _boardId = boardId;\n\n        _column = new()\n            {\n                Name = string.Empty,\n                BoardId = boardId,\n                Index = 0\n            };\n        _editContext = new EditContext(_column);\n\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if (Modal is null || _editContext is null || _column is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var board = await db.Boards.Include(x => x.Columns).FirstOrDefaultAsync(x => x.Id.Equals(_boardId));\n\n        if (board is not null)\n        {\n            _column.Index = board.Columns.GetNextIndex();\n\n            board.Columns.Add(_column);\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/CreateProjectModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"New project\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    <EditForm class=\"form\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator/>\n        \n        <div class=\"form-group\">\n            <Name For=\"() => _project.Name\"/>\n            <InputText class=\"form-control\" @bind-Value=\"_project.Name\" @ref=\"FocusElement\" />\n            <ValidationMessage For=\"() => _project.Name\" />\n        </div>\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Project _project = new()\n    {\n        Name = string.Empty\n    };\n\n    private EditContext? _editContext;\n\n    protected override void OnOpen()\n    {\n        _project = new()\n            {\n                Name = string.Empty\n            };\n        _editContext = new EditContext(_project);\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if(Modal is null || _editContext is null || _project is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var user = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if (user is not null)\n        {\n            var membership = new ProjectMembership\n            {\n                IsAdmin = true,\n                ProjectId = _project.Id,\n                UserId = user.Id,\n                AddedAt = DateTime.Now\n            };\n            _project.Memberships.Add(membership);\n            db.Projects.Add(_project);\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/DeleteConfirmationDialog.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n@typeparam T where T : class, IDbEntry, IDeletable\n\n<Modal @ref=_dialog OnSubmitAttempted=\"HandleSubmit\" RedSubmit=true Title=@($\"Delete {_entityName} {_obj?.Name}\")>\n    @if(_obj is null)\n    {\n        <Spinner/>\n    } else {\n        <p>\n            Are you sure you'd like to delete the @_entityName <b>@_obj.Name</b>?<br />\n            All data associated with this @_entityName will be deleted.<br />\n            <b>This action is irreversible.</b>\n        </p>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    protected MainLayout MainLayout { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnConfirmed { get; set; } = default!;\n\n    private string _entityName = typeof(T).Name.ToFriendlyName().ToLower();\n    private T? _obj;\n    private Modal? _dialog;\n    private Func<Task>? _onSubmitDelegate { get; set; } = default!;\n\n    public async Task OpenDialog(T obj, Func<Task>? onSubmitDelegate = null)\n    {\n        if (_dialog is null)\n            return;\n\n        _obj = obj;\n        _onSubmitDelegate = onSubmitDelegate;\n        StateHasChanged();\n\n        if (_user.InstantDelete)\n        {\n            await HandleSubmit();\n            return;\n        }\n\n        await _dialog.Show();\n    }\n\n    protected async Task HandleSubmit()\n    {\n        if (_dialog is null || _obj is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await db.Set<T>().Where(x => x.Id.Equals(_obj.Id)).ExecuteDeleteAsync();\n\n        if (_onSubmitDelegate is not null)\n            await _onSubmitDelegate.Invoke();\n\n        MainLayout.RunNotification(new Notification($\"{typeof(T).Name.ToFriendlyName()} deleted successfully.\"));\n        await OnConfirmed.InvokeAsync();\n        await _dialog.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditBoardMembershipsModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=@($\"Edit memberships for board {_board?.Name}\") DisableButtons=\"true\" EnableTitle=\"true\">\n    @if(_board is null || _project is null)\n    {\n        <Spinner/>\n    } else\n    {\n        <div class=\"flex flex-col items-center gap-3\">\n            <div class=\"flex w-full flex-row items-center gap-3\">\n                <input class=\"w-full rounded-lg bg-search-bar px-2 py-1 text-sm\" type=\"text\"\n                       placeholder=\"Enter e-mail address\" @oninput=\"OnInviteTextChanged\" @ref=\"FocusElement\" />\n                <button class=\"px-3 py-1.5\" @onclick=\"AddAccess\">Add</button>\n            </div>\n\n            <label class=\"text-sm\">Board members</label>\n            <table class=\"border-separate border-spacing-x-5 border-spacing-y-1\">\n                @foreach(var membership in _board.Memberships.OrderByDescending(x => x.IsAdmin).ThenBy(x => x.AddedAt))\n                {\n                    <tr class=\"text-sm\">\n                        <td>\n                            <div class=\"avatar\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@membership.User.ProfilePictureFileName');\"></div>\n                        </td>\n                        <td>\n                            @membership.User.DisplayName @(membership.UserId.Equals(_user.Id) ? \"(you)\" : string.Empty)\n                        </td>\n                        <td>\n                            <Dropdown Disabled=\"@membership.UserId.Equals(_user.Id)\" Actions='new() {\n                                { \"Admin\", () => ChangeAdmin(membership.Id, true)},\n                                { \"Member\", () => ChangeAdmin(membership.Id, false)}\n                            }'>\n                        <div class='flex flex-row items-center justify-between pr-2 pl-5 transition-all ease-in-out @(!membership.UserId.Equals(_user.Id) ? \"bg-full-dropdown hover:bg-full-dropdown-hover cursor-pointer\" : \"bg-gray-100 cursor-not-allowed\")'>\n                                    @(membership.IsAdmin ? \"Admin\" : \"Member\")\n                                    <i class='fa fa-chevron-down edit-icon @(membership.UserId.Equals(_user.Id) ? \"!cursor-not-allowed\" : string.Empty)' title=\"Change role\"></i>\n                                </div>\n                            </Dropdown>\n                        </td>\n                        <td>\n                            <i @onclick=\"() => RemoveUser(membership.UserId)\" \n                                class='fa fa-trash edit-icon @(membership.UserId.Equals(_user.Id) ? \"!text-disabled-icon !hover:text-disabled-icon !cursor-not-allowed\" : string.Empty)' title=\"Remove member\">\n                            </i>\n                        </td>\n                    </tr>\n                }\n            </table>\n\n            <label class=\"text-sm\">Project members</label>\n            <table class=\"border-separate border-spacing-x-5 border-spacing-y-1\">\n                @{\n                    var i = 0;\n                }\n                @foreach (var membership in _project.Memberships.OrderByDescending(x => x.IsAdmin).ThenBy(x => x.AddedAt))\n                {\n                    string avatarId = $\"avatar_{i}\";\n                    <tr class=\"text-sm\">\n                        <td>\n                            <div id=\"@avatarId\" @onclick=\"() => _mainLayout.UserInfoModal?.Open(avatarId, membership.UserId)\" class=\"avatar\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@membership.User.ProfilePictureFileName');\"></div>\n                        </td>\n                        <td>\n                            @membership.User.DisplayName @(membership.UserId.Equals(_user.Id) ? \"(you)\" : string.Empty)\n                        </td>\n                        <td>\n                            <div class=\"flex cursor-not-allowed flex-row items-center justify-between bg-search-bar pr-2 pl-5 transition-all ease-in-out\">\n                                @(membership.IsAdmin ? \"Admin\" : \"Member\")\n                                <i class=\"fa fa-chevron-down edit-icon !text-disabled-icon !cursor-not-allowed !hover:text-disabled-icon\"></i>\n                            </div>\n                        </td>\n                        <td>\n                            <i class=\"fa fa-trash edit-icon !text-disabled-icon !cursor-not-allowed !hover:text-disabled-icon\"></i>\n                        </td>\n                    </tr>\n\n                    i++;\n                }\n            </table>\n        </div>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Project? _project;\n    private Board? _board;\n    private string _inviteText = string.Empty;\n\n    public async void Open(int boardId, int projectId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _board = await db.Boards\n            .AsNoTracking()\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(boardId));\n\n        if (_board is null)\n            return;\n\n        _project = await db.Projects\n            .AsNoTracking()\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_board.ProjectId));\n\n        if (_project is null)\n            return;\n\n        StateHasChanged();\n\n        base.Open();\n    }\n\n    private void OnInviteTextChanged(ChangeEventArgs e) \n    {\n        _inviteText = e.Value?.ToString() ?? string.Empty;\n    }\n\n    private async Task AddAccess() \n    {\n        if(_board is null || _project is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if (board is null)\n            return;\n\n        var targetUser = await db.Users.\n            FirstOrDefaultAsync(x => x.Email != null && x.Email.Equals(_inviteText));\n\n        if(targetUser is null)\n        {\n            _mainLayout.RunNotification(new Notification(\"There is no user with the provided e-mail address.\", NotificationType.Fail));\n            return;\n        }\n\n        if (board.Memberships.Any(x => x.UserId.Equals(targetUser.Id)) || targetUser.Id.Equals(_user.Id))\n        {\n            _mainLayout.RunNotification(new Notification(\"This user already has access to this board.\", NotificationType.Fail));\n            return;\n        }\n\n        var membership = new BoardMembership\n        {\n            BoardId = board.Id,\n            IsAdmin = false,\n            UserId = targetUser.Id,\n            AddedAt = DateTime.Now\n        };\n\n        board.Memberships.Add(membership);\n        await db.SaveChangesAsync();\n\n        _board = board;\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async void ChangeAdmin(int membershipId, bool value)\n    {\n        if (_board is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var targetMembership = await db.BoardMemberships.FirstOrDefaultAsync(x => x.Id.Equals(membershipId));\n\n        if (targetMembership is null)\n            return;\n\n        targetMembership.IsAdmin = value;\n        await db.SaveChangesAsync();\n\n        _board.Memberships.First(x => x.Id.Equals(membershipId)).IsAdmin = value;\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async Task RemoveUser(int userId)\n    {\n        if (_board is null || userId.Equals(_user.Id))\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if (board is null)\n            return;\n\n        var targetMembership = board.Memberships.FirstOrDefault(x => x.UserId.Equals(userId));\n\n        if(targetMembership is null)\n            return;\n\n        board.Memberships.Remove(targetMembership);\n        await db.SaveChangesAsync();\n\n        _board = board;\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditBoardModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"Edit board\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    @if (_board is not null)\n    {\n        <EditForm class=\"form\" EditContext=\"  _editContext\">\n            <DataAnnotationsValidator />\n            \n            <div class=\"form-group\">\n                <Name For=\" () => _board.Name\" />\n                <InputText class=\"form-control\" @bind-Value=\"_board.Name\" @ref=\"FocusElement\" />\n                <ValidationMessage For=\"  () => _board.Name\" />\n            </div>\n                \n            <div class=\"form-group\">\n                <Name For=\"() => _board.Description\" />\n                <InputText class=\"form-control\" @bind-Value=\"_board.Description\" />\n                <ValidationMessage For=\" () => _board.Description\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _board.Code\" />\n                <InputText class=\"form-control\" @bind-Value=\"_board.Code\" />\n                <ValidationMessage For=\" () => _board.Code\" />\n            </div>\n        </EditForm>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Board? _board;\n\n    private EditContext? _editContext;\n\n    public async Task Open(int boardId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n        _board = await db.Boards\n            .AsNoTracking()\n            .FirstOrDefaultAsync(x => x.Id.Equals(boardId));\n\n        if (_board is null)\n            return;\n\n        _editContext = new EditContext(_board);\n\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if (Modal is null || _editContext is null || _board is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var targetBoard = await db.Boards.FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if (targetBoard is not null)\n        {\n            targetBoard.Name = _board.Name;\n            targetBoard.Description = _board.Description;\n            targetBoard.Code = _board.Code;\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditCardModal.razor",
    "content": "﻿@inherits AbstractModal\n@implements IDisposable\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject IJSRuntime _js\n@inject NavigationManager _navigationManager\n@inject ILogger<EditCardModal> _logger\n\n<PriorityModal @ref=_priorityModal UpdateCard=\"UpdateCard\" />\n<LabelModal @ref=_labelModal UpdateCard=\"UpdateCard\" />\n<AssigneesModal @ref=_assigneesModal UpdateCard=\"UpdateCard\" />\n<AddSubtaskModal @ref=_addSubtaskModal UpdateCard=\"UpdateCard\" />\n<AddReminderModal @ref=_addReminderModal UpdateCard=\"UpdateCard\" />\n<AddTimeRecordModal @ref=_addTimeRecordModal UpdateCard=\"UpdateCard\" />\n<EditTimeRecordModal @ref=_editTimeRecordModal UpdateCard=\"UpdateCard\" />\n<EditSubtaskModal @ref=_editSubtaskModal UpdateCard=\"UpdateCard\" />\n<EditDeadlineModal @ref=_editDeadlineModal UpdateCard=\"UpdateCard\" />\n<LinkCardsModal @ref=_linkCardsModal UpdateCard=\"UpdateCard\" />\n<SnoozeCardModal @ref=_snoozeCardModal UpdateCard=\"UpdateCard\" />\n<AddOrEditRepeatModal @ref=_repeatCardModal UpdateCard=\"UpdateCard\" />\n<SearchModal CardToLink=_card LinkCardsModal=\"_linkCardsModal\" @ref=_searchModal/>\n\n<Modal @ref=\"Modal\" Large=true Title=\"Edit an existing task\" DisableButtons=true OnClose=\"OnClose\">\n    @if (_card is null || _columns is null)\n    {\n        <Spinner />\n    }\n    else\n    {\n        <div class=\"h-[90vh] overflow-x-hidden overflow-y-scroll\" @ref=\"_scrollContainerRef\">\n            <div class=\"flex flex-col gap-3 px-5 py-5\">\n                <i class=\"edit-icon fa fa-x ml-auto\" @onclick=\"async () => await Modal!.Close()\" title=\"Close\"></i>\n                <textarea class=\"min-h-12 resize-none px-2 py-2 text-2xl font-bold transition-all ease-in-out\" @onchange=\"OnTextChanged\">@_card.Name</textarea>\n                <hr />\n                <table class=\"ml-2 border-separate border-spacing-3\">\n                    <tbody>\n                        <tr>\n                            <td class=\"edit-task-label\">ID</td>\n                            <td class=\"edit-task-item flex-wrap\">\n                                @(_card.Column.Board.Code)-@_card.Number\n                                <i class=\"fa fa-link edit-icon\" title=\"Copy to clipboard the deep link to this specific card\" @onclick=\"CopyDeepLink\"></i>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Priority</td>\n                            <td class=\"edit-task-item\">\n                                <div @ref=\"_priorityDiv\" @onclick=\"() => _priorityModal?.Open(_priorityDiv, _card)\">\n                                    <PriorityLabel Priority=\"_card.Priority\" />\n                                </div>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Assignees</td>\n                            <td class=\"edit-task-item flex-wrap\">\n                                @{\n                                    var i = 0;\n                                }\n                                @foreach(var assignee in _card.Assignees.OrderBy(x => x.DisplayName)) \n                                {\n                                    var assigneeId = $\"avatar_1_{i}\";\n\n                                    <div id=\"@assigneeId\" class=\"person-label cursor-pointer\" @onclick=\"() => _mainLayout.UserInfoModal?.Open(assigneeId, assignee.Id)\">\n                                        <div style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@assignee.ProfilePictureFileName');\"></div>\n                                        <label class=\"cursor-pointer\">@assignee.DisplayName</label>\n                                    </div>\n\n                                    i++;\n                                }\n                                <i @ref=\"_assigneesTrigger\" class=\"fa fa-pencil edit-icon\" @onclick=\"() => _assigneesModal?.Open(_assigneesTrigger, _card, _members)\" title=\"Edit assignees\"></i>\n                                @if (_card.Assignees.Any(x => x.Id.Equals(_user.Id)))\n                                {\n                                    <i class=\"fa-solid fa-user-minus edit-icon\" @onclick=\"Leave\" title=\"Leave task\"></i>\n                                }\n                                else\n                                {\n                                    <i class=\"fa-solid fa-user-plus edit-icon\" @onclick=\"Join\" title=\"Join task\"></i>\n                                }\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Current list</td>\n                            <td class=\"edit-task-item\">\n                                @_card.Column.Name\n                                @if (_card.Column.Index != 0)\n                                {\n                                    <i class=\"fa fa-left-long edit-icon\" @onclick=\"MoveToPreviousList\" title=\"Move to previous column\"></i>\n                                }\n                                @if (_lastColumnIndex != _card.Column.Index)\n                                {\n                                    <i class=\"fa fa-right-long edit-icon\" @onclick=\"MoveToNextList\" title=\"Move to next column\"></i>\n                                }\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Labels</td>\n                            <td class=\"edit-task-item\">\n                                @foreach(var label in _card.Labels) {\n                                    <LabelView Label=\"label\"></LabelView>\n                                }\n                                <i @ref=\"_labelDiv\" class=\"fa fa-pencil edit-icon\" @onclick=\"() => _labelModal?.Open(_labelDiv, _card, _card.Column.Board.Labels)\" title=\"Edit labels\"></i>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Reminders</td>\n                            <td class=\"edit-task-item\">\n                                @if(Constants.SMTP_ENABLED)\n                                {\n                                    @foreach(var reminder in _card.Reminders.OrderBy(x => x.At)) \n                                    {\n                                        <div class=\"card-label\">\n                                            <label class=\"whitespace-nowrap\">@reminder.At.ToReadableStringWithTime()</label>\n                                            <i class=\"fa fa-trash-can cursor-pointer text-red-button transition-all ease-in-out hover:text-red-button-hover\" @onclick=\"() => DeleteReminder(reminder)\" title=\"Delete reminder\"></i>\n                                        </div>\n                                    }\n                                    <i @ref=\"_addReminderTrigger\" class=\"fa fa-pencil edit-icon\" @onclick=\"() => _addReminderModal?.Open(_addReminderTrigger, _card)\" title=\"Add reminder\"></i>\n                                } else\n                                {\n                                    <Tooltip Text=\"Reminders cannot be used without SMTP\">\n                                        <DisabledBadge/>\n                                    </Tooltip>\n                                }\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Deadline</td>\n                            <td class=\"edit-task-item\">\n                                @if(_card.Deadline is not null)\n                                {\n                                    <div class=\"card-label\">\n                                        <label class=\"whitespace-nowrap\">@_card.Deadline.Value.ToReadableStringWithTime()</label>\n                                        <i class=\"fa fa-trash-can cursor-pointer text-red-button transition-all ease-in-out hover:text-red-button-hover\" @onclick=\"DeleteDeadline\" title=\"Remove deadline\"></i>\n                                    </div>\n                                }\n                                <i @ref=\"_editDeadlineTrigger\" class=\"fa fa-pencil edit-icon\" @onclick=\"() => _editDeadlineModal?.Open(_editDeadlineTrigger, _card)\" title=\"Edit deadline\"></i>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Snooze</td>\n                            <td class=\"edit-task-item\">\n                                @if (_card.SnoozedUntil.HasValue)\n                                {\n                                    <div class=\"card-label\">\n                                        <label class=\"whitespace-nowrap\">@_card.SnoozedUntil.Value.ToReadableStringWithTime()</label>\n                                        <i class=\"fa fa-trash-can cursor-pointer text-red-button transition-all ease-in-out hover:text-red-button-hover\" @onclick=\"UnsnoozeCard\" title=\"Remove snooze\"></i>\n                                    </div>\n                                }\n                                <i @ref=\"_snoozeTrigger\" class=\"fa fa-moon edit-icon\" @onclick=\"() => _snoozeCardModal?.Open(_snoozeTrigger, _card)\" title=\"Snooze card\"></i>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Repeat [BETA]</td>\n                            <td class=\"edit-task-item\">\n                                @if (_card.RepeatInfo is not null)\n                                {\n                                    <div class=\"card-label\">\n                                        <label class=\"whitespace-nowrap\">@_card.RepeatInfo.GetRepeatString() (next on @_card.CalculateNextRepeat(DateTime.Now).ToReadableStringWithTime())</label>\n                                        <i class=\"fa fa-trash-can cursor-pointer text-red-button transition-all ease-in-out hover:text-red-button-hover\" @onclick=\"RemoveRepeat\" title=\"Remove repeat\"></i>\n                                    </div>\n                                }\n                                <i @ref=\"_repeatTrigger\" class=\"fa fa-repeat edit-icon\" @onclick=\"() => _repeatCardModal?.Open(_repeatTrigger, _card, _columns)\" title=\"Edit repeat settings\"></i>\n                            </td>\n                        </tr>\n                        <tr>\n                            <td class=\"edit-task-label\">Created by</td>\n                            <td class=\"edit-task-item\">\n                                @{\n                                    var createdById = \"created_by\";\n                                }\n                                <div id=@createdById class=\"person-label cursor-pointer\" @onclick=\"() => _mainLayout.UserInfoModal?.Open(createdById, _card.CreatedById)\">\n                                    <div style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_card.CreatedBy.ProfilePictureFileName');\"></div>\n                                    <label class=\"cursor-pointer\">@_card.CreatedBy.DisplayName</label>\n                                </div>\n                            </td>\n                        </tr>\n                    </tbody>\n                </table>\n                <div class=\"flex flex-row text-sm\">\n                    <label data-active=@((_tab == 0).ToString()) class=\"cursor-pointer border-b-2 px-4 py-2 transition-all select-none hover:border-add-outline data-[active=True]:border-card-header-highlight\" @onclick=\"() => _tab = 0\">\n                        <label class=\"hidden cursor-pointer sm:block\">Description</label>\n                        <i class=\"fa fa-circle-info sm:!hidden\" title=\"Description\"></i>\n                    </label>\n                    <label data-active=@((_tab == 1).ToString()) class=\"cursor-pointer border-b-2 px-4 py-2 transition-all select-none hover:border-add-outline data-[active=True]:border-card-header-highlight\" @onclick=\"() => _tab = 1\">\n                        <label class=\"hidden cursor-pointer sm:block\">Comments</label>\n                        <i class=\"fa fa-comments sm:!hidden\" title=\"Comments\"></i>\n                    </label>\n                    <label data-active=@((_tab == 2).ToString()) class=\"cursor-pointer border-b-2 px-4 py-2 transition-all select-none hover:border-add-outline data-[active=True]:border-card-header-highlight\" @onclick=\"() => _tab = 2\">\n                        <label class=\"hidden cursor-pointer sm:block\">Activity</label>\n                        <i class=\"fa fa-rotate-right sm:!hidden\" title=\"Activity\"></i>\n                    </label>\n                    <label data-active=@((_tab == 3).ToString()) class=\"cursor-pointer border-b-2 px-4 py-2 whitespace-nowrap transition-all select-none hover:border-add-outline data-[active=True]:border-card-header-highlight\" @onclick=\"() => _tab = 3\">\n                        <label class=\"hidden cursor-pointer sm:block\">Time Tracking</label>\n                        <i class=\"fa fa-clock sm:!hidden\" title=\"Time tracking\"></i>\n                    </label>\n                    <label class=\"w-full border-b-2 px-2 py-2\"></label>\n\n                </div>\n                @if (_tab == 0)\n                {\n                    <textarea @onchange=\"OnDescriptionChanged\" \n                        class=\"h-24 w-full resize-none overflow-auto rounded-lg bg-search-bar p-4 text-sm outline-0 outline-typing-outline transition-all ease-in-out focus:outline-2\"\n                              placeholder=\"Might be the time for some additional information ...\">@_card.Description</textarea>\n                    <hr />\n                    <section class=\"flex flex-col gap-2\">\n                        <div class=\"flex flex-row items-center gap-2 text-xs\">\n                            <h5 class=\"font-normal text-card-heading select-none\">LINKED CARDS</h5>\n                            <i id=\"linked_cards\" class=\"fa fa-plus edit-icon !p-0\" @onclick='() => _searchModal?.Open()' title=\"Link cards\"></i>\n                        </div>\n                        @foreach(var group in _card.LinkedIssuesOne.GroupBy(x => x.Category)) \n                        {\n                            <label class=\"text-sm\">@group.Key</label>\n                            @foreach(var linkedCardLink in group) \n                            {\n                                var linkedCard = linkedCardLink.CardTwo;\n                                <div class=\"flex cursor-pointer flex-col justify-between rounded-sm px-3 py-2 text-xs shadow outline-1 outline-add-outline transition-all ease-in-out hover:bg-dropdown-option\">\n                                    <div class=\"flex flex-row justify-between gap-3\">\n                                        <label class=\"cursor-pointer whitespace-nowrap\">@linkedCard.Column.Board.Code-@linkedCard.Number</label>\n                                        <label class=\"cursor-pointer truncate whitespace-nowrap\">@linkedCard.Name</label>\n                                    </div>\n                                    <div class=\"flex flex-row items-center justify-between\">\n                                        <label class=\"text-2xs cursor-pointer font-light\">Project @linkedCard.Column.Board.Project.Name — @linkedCard.Column.Name</label>\n                                        <i class=\"fa fa-trash-can edit-icon !p-0 !text-red-button hover:!text-red-button-hover\" @onclick=\"() => DeleteLink(linkedCardLink)\" @onclick:stopPropagation=true title=\"Remove link\"></i>\n                                    </div>\n                                </div>\n                            }\n                        }\n                    </section>\n                    <hr />\n                    <section class=\"flex flex-col gap-2\">\n                        <div class=\"flex flex-row items-center gap-3 text-xs\">\n                            <h5 class=\"font-normal text-card-heading select-none\">SUB-TASKS</h5>\n                            <i @ref=\"_addSubtaskTrigger\" class=\"fa fa-plus edit-icon !p-0\" @onclick=\"() => _addSubtaskModal?.Open(_addSubtaskTrigger, _card)\" title=\"Add subtask\"></i>\n                        </div>\n                        @if (_subtasks is null)\n                        {\n                            <div class=\"flex flex-col gap-2 pl-3\">\n                                @for (int s = 0; s < 6; s++)\n                                {\n                                    <div class=\"flex flex-row items-center gap-2\">\n                                        <div class=\"h-4 w-4 animate-pulse rounded bg-slate-200\"></div>\n                                        <div class=\"h-4 w-full animate-pulse rounded bg-slate-200\"></div>\n                                    </div>\n                                }\n                            </div>\n                        }\n                        else if (_subtasks.Any())\n                        {\n                            <div class=\"flex flex-row items-center justify-between gap-2 px-3 py-2\">\n                                @{\n                                    double percentage = Math.Round((_subtasks.Where(x => x.Completed).Count() / (double)_subtasks.Count) * 100);\n                                }\n                                <label class=\"w-9 text-center text-xs text-stone-500\">@percentage%</label>\n                                <div class=\"grid h-3 w-full overflow-hidden rounded-lg\">\n                                    <div class=\"h-full w-full bg-gray-300\" style=\"grid-column: 1; grid-row: 1;\"></div>\n                                    <div class='z-10 @(percentage != 100 ? \"bg-blue-400\" : \"bg-green-400\") block h-full transition-all' style=\"grid-column: 1; grid-row: 1; width: @percentage%;\"></div>\n                                </div>\n                            </div>\n                            <div class=\"flex flex-col gap-2 pl-3\">\n                                <SortableList Class=\"flex flex-col gap-2\" Animation=@(_card.Column.Board.DisableSortingAnimations ? 0 : 200) Items=\"_subtasks.OrderBy(x => x.Index).ToList()\" OnUpdate=\"OnSubtaskMoved\" Handle=\".drag-toggle\">\n                                    <SortableItemTemplate>\n                                        <SubtaskView @key=\"context.Id\" Subtask=\"context\" AssigneesModal=\"_assigneesModal\" EditSubtaskModal=\"_editSubtaskModal\" Members=\"_members\" UpdateCard=\"UpdateCard\" />\n                                    </SortableItemTemplate>\n                                </SortableList>\n                            </div>\n                        }\n                    </section>\n                    <hr />\n                    <section class=\"flex flex-col gap-4\">\n                        <h5 class=\"text-xs font-normal text-card-heading select-none\">ATTACHMENTS</h5>\n                        <label class=\"add h-min w-full rounded-lg px-5 py-5 select-none\" for=\"file-upload\">\n                            <i class=\"fa fa-file-arrow-down text-3xl\" title=\"Upload attachment\"></i>\n                            <label>Upload attachment</label>\n                            <InputFile class=\"hidden\" multiple id=\"file-upload\" OnChange=\"OnFileChanged\"/>\n                        </label>\n                        <div class=\"flex flex-row flex-wrap items-center justify-start gap-2\">\n                            @foreach(var attachment in _card.Attachments) \n                            {\n                                <div class=\"flex w-min cursor-pointer flex-row items-center justify-center gap-2 rounded-lg px-2 py-2 outline-2 outline-add-outline transition-all ease-in-out select-none hover:outline-add-outline-hover\"\n                                    @onclick=\"() => DownloadAttachment(attachment)\">\n                                    <div class=\"h-8 w-8 bg-cover bg-center\" style=\"background-image: url('./images/icons/@AttachmentHelper.GetImageNameFromAttachment(attachment)');\" />\n                                    <div class=\"flex flex-col text-xs font-normal\">\n                                        <label class=\"cursor-pointer font-medium\">@attachment.OriginalName</label>\n                                        <div class=\"flex flex-row gap-2\">\n                                            <label class=\"cursor-pointer text-add-outline\">@AttachmentHelper.GetFileTypeFromAttachment(attachment)</label>\n                                            <label class=\"ml-auto cursor-pointer text-red-button hover:text-red-button-hover\" @onclick=\"() => DeleteAttachment(attachment)\" @onclick:stopPropagation=true><i class=\"fa fa-trash-can\" title=\"Delete attachment\"></i></label>\n                                        </div>\n                                    </div>\n                                </div>\n                            }\n                        </div>\n                    </section>\n                }\n                else if (_tab == 1)\n                {\n                    <textarea class=\"h-24 w-full overflow-auto rounded-lg bg-search-bar p-4 text-sm outline-0 outline-typing-outline transition-all ease-in-out focus:outline-2\" \n                        @oninput=\"OnCommentTextChanged\" value=\"@_commentText\"\n                        placeholder=\"Say what's on your mind ...\"></textarea>\n                    <div class=\"flex flex-row justify-end\">\n                        <button class=\"w-min px-4 py-2\" @onclick=\"PostComment\">Submit</button>\n                    </div>\n                    <hr />\n                    @if (_card.Comments.Any())\n                    {\n                        int j = 0;\n                        @foreach (var comment in _card.Comments.OrderByDescending(x => x.CreatedAt))\n                        {\n                            <div class=\"flex flex-col gap-1\">\n                                <div class=\"flex flex-row items-center gap-2\">\n                                    @{\n                                        var commentId = $\"comment_id_{i}\";\n                                    }\n                                    @if(comment.CreatedBy is not null) \n                                    {\n                                        <div id=@commentId class=\"avatar\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@comment.CreatedBy.ProfilePictureFileName');\"\n                                             @onclick=\"() => _mainLayout.UserInfoModal?.Open(commentId, comment.CreatedById)\"></div>\n                                    } else {\n                                        <div id=@commentId class=\"avatar\" style=\"background-image: url('./images/question_mark_avatar.png');\"></div>\n                                    }\n                                    <label id=@commentId class=\"cursor-pointer text-sm font-medium\" @onclick=\"() => _mainLayout.UserInfoModal?.Open(commentId, comment.CreatedById)\">@(comment.CreatedBy?.DisplayName ?? \"Deleted User\")</label>\n                                    <label class=\"text-xs text-gray-400\">@TimeHelper.ToElapsedString(comment.CreatedAt)</label>\n                                </div>\n                                <label class=\"text-sm font-normal break-normal break-words\">@comment.Text</label>\n                            </div>\n\n                            j++;\n                        }\n                    }\n                    else\n                    {\n                        <label class=\"text-sm font-normal\">There are no comments here yet.</label>\n                    }\n                }\n                else if (_tab == 2)\n                {\n                    <div class=\"flex flex-col gap-1 border-l-2\">\n                        @{\n                            DateTime? lastDay = null;\n                            i = 0;\n                            var onlyFirstDates = _card.Activities.OrderBy(x => x.CreatedAt).GroupBy(x => x.CreatedAt.Date).Select(x => x.OrderBy(y => y.CreatedAt.Date).First()).Select(x => x.CreatedAt).ToList();\n\n                            onlyFirstDates.RemoveAll(x => x.Date.Equals(_card.CreatedAt.Date));\n                            onlyFirstDates.Add(_card.CreatedAt);\n                        }\n                        @foreach (var activity in _card.Activities.OrderByDescending(x => x.CreatedAt))\n                        {\n                            var activityId = $\"activity_id_{i}\";\n\n                            <div class=\"flex flex-row items-center justify-between py-2 text-xs\">\n                                <div class='ml-[-5px] h-2 max-w-2 min-w-2 rounded-full bg-add-outline @(onlyFirstDates.Any(x => DateTime.Compare(activity.CreatedAt, x) == 0) ? string.Empty : \"opacity-0\")'></div>\n                                <label class=\"ml-3 whitespace-nowrap text-add-outline capitalize\">@activity.CreatedAt.ToShortString()</label>\n                                <label class=\"ml-6\"><label class=\"person-link\" id=\"@activityId\"\n                                    @onclick=\"() => _mainLayout.UserInfoModal?.Open(activityId, activity.UserId)\">\n                                    @@@activity.User.DisplayName</label> @((MarkupString) activity.Text).\n                                </label>\n                                <label class=\"ml-auto whitespace-nowrap text-add-outline\">@activity.CreatedAt.ToElapsedString()</label>\n                            </div>\n\n                            lastDay = DateTime.Now;\n                            i++;\n                        }\n\n                        @{\n                            var finalActivityId = $\"activity_id_{i}\";\n                        }\n                        <div class=\"flex flex-row items-center justify-between py-2 text-xs\">\n                            <div class=\"ml-[-5px] h-2 w-2 rounded-full bg-add-outline\"></div>\n                            <label class=\"ml-3 whitespace-nowrap text-add-outline capitalize\">@_card.CreatedAt.ToShortString()</label>\n                            <label class=\"ml-6\"><label class=\"person-link\" id=\"@finalActivityId\"\n                                @onclick=\"() => _mainLayout.UserInfoModal?.Open(finalActivityId, _card.CreatedById)\">\n                                @@@_card.CreatedBy.DisplayName</label> <b>created</b> this card.\n                            </label>\n                            <label class=\"ml-auto whitespace-nowrap text-add-outline\">@_card.CreatedAt.ToElapsedString()</label>\n                        </div>\n                    </div>\n                }\n                else if (_tab == 3)\n                {\n                    <div class=\"flex w-full flex-col gap-3 text-sm select-none\">\n                        <div class=\"flex flex-row items-center justify-start gap-1\">\n                            <div class=\"flex flex-row items-center gap-2\">\n                                <label>Total time:</label> <div class=\"rounded-lg bg-search-bar px-1 py-0.5 font-bold\">@(new TimeSpan(_card.TimeRecords.Select(x => ((x.EndedAt ?? DateTime.Now) - x.StartedAt).Ticks).Sum()).ToElapsedString())</div>\n                            </div>\n                            @{\n                                var ongoingTimer = _card.TimeRecords.Where(x => x.UserId.Equals(_user.Id) && x.EndedAt == null).FirstOrDefault();\n                                var timeRecordCreateId = \"time_record_create\";\n                            }\n                            <div class=\"ml-auto flex flex-row items-center gap-2\">\n                                <button class=\"px-2\" id=@timeRecordCreateId @onclick=\"() => _addTimeRecordModal?.Open(timeRecordCreateId, _card)\">Add time</button>\n                                @if (ongoingTimer is null)\n                                {\n                                    <button class='!bg-green-button px-2 hover:!bg-green-button-hover' @onclick=\"StartTimer\">Start timer</button>\n                                } else {\n                                    <button class='!bg-red-button px-2 !hover:bg-red-button-hover' @onclick=\"() => EndTimer(ongoingTimer)\">@_ongoingTimer.ToElapsedString()</button>\n                                }\n                            </div>\n                        </div>\n                        @foreach(var timeRecord in _card.TimeRecords.Where(x => x.EndedAt != null).OrderByDescending(x => x.EndedAt)) \n                        {\n                            string userTimeRecordId = $\"user_time_record_{timeRecord.Id}\";\n                            string timeRecordId = $\"time_record_{timeRecord.Id}\";\n\n                            <div class=\"flex flex-row items-center justify-start gap-3\">\n                                <div id=\"@userTimeRecordId\" class=\"avatar\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@timeRecord.User.ProfilePictureFileName');\"\n                                    @onclick=\"() => _mainLayout.UserInfoModal?.Open(userTimeRecordId, timeRecord.UserId)\"></div>\n                                <div class=\"flex w-full flex-row items-center justify-between\">\n                                    <div class=\"flex flex-col items-start justify-center\">\n                                        <label>@timeRecord.User.DisplayName</label>\n                                        <label class=\"font-bold\">@((timeRecord.EndedAt!.Value - timeRecord.StartedAt).ToElapsedString())</label>\n                                    </div>\n\n                                    <div class=\"flex flex-row items-center\">\n                                        <i id=\"@timeRecordId\" class=\"fa fa-pencil edit-icon\" @onclick=\"() => _editTimeRecordModal?.Open(timeRecordId, timeRecord)\" title=\"Edit time record\"></i>\n                                        <i class=\"fa fa-trash-can edit-icon !text-red-button hover:!text-red-button-hover\" @onclick=\"() => DeleteTimeRecord(timeRecord)\" title=\"Delete time record\"></i>\n                                    </div>\n                                </div>\n                            </div>\n                        }\n                    </div>\n                }\n            </div>\n        </div>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Card? _card;\n    private List<Subtask>? _subtasks;\n    private List<User> _members = [];\n    private List<Column>? _columns;\n\n    private ElementReference? _labelDiv;\n    private ElementReference? _priorityDiv;\n    private ElementReference? _assigneesTrigger;\n    private ElementReference? _addSubtaskTrigger;\n    private ElementReference? _addReminderTrigger;\n    private ElementReference? _editDeadlineTrigger;\n    private ElementReference? _snoozeTrigger;\n    private ElementReference? _repeatTrigger;\n    private LabelModal? _labelModal;\n    private PriorityModal? _priorityModal;\n    private AssigneesModal? _assigneesModal;\n    private AddSubtaskModal? _addSubtaskModal;\n    private AddReminderModal? _addReminderModal;\n    private AddTimeRecordModal? _addTimeRecordModal;\n    private EditTimeRecordModal? _editTimeRecordModal;\n    private EditSubtaskModal? _editSubtaskModal;\n    private EditDeadlineModal? _editDeadlineModal;\n    private LinkCardsModal? _linkCardsModal;\n    private SnoozeCardModal? _snoozeCardModal;\n    private AddOrEditRepeatModal? _repeatCardModal;\n    private SearchModal? _searchModal;\n\n    private DotNetObjectReference<EditCardModal>? _pasteObjRef;\n\n    private int _tab = 0;\n    private string _identifier = string.Empty;\n    private string _commentText = string.Empty;\n    private int _lastColumnIndex;\n    private System.Timers.Timer? _timer;\n    private TimeSpan _ongoingTimer;\n    private ElementReference _scrollContainerRef;\n\n    public async Task Open(int cardId, List<User> members, List<Column> columns)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n        _card = await GetNoTrackingCard(db, cardId);\n\n        if (_card is null)\n            return;\n\n        _members = members;\n        _columns = columns;\n        _subtasks = null;\n\n        _identifier = $\"{_card.Column.Board.Code}-{_card.Number}\";\n        UpdateTimer();\n        base.Open();\n    }\n\n    protected override void OnOpen()\n    {\n        _pasteObjRef = DotNetObjectReference.Create(this);\n        _ = _js.InvokeVoidAsync(\"attachCardPasteHandler\", _pasteObjRef, _card!.Id);\n        _ = LoadSubtasksAsync();\n    }\n\n    [JSInvokable]\n    public async Task OnPastedUploadFinished()\n    {\n        _mainLayout.RunNotification(new Notification(\"File uploaded successfully.\"));\n        await UpdateCard();\n    }\n\n    [JSInvokable]\n    public void OnPastedUploadFailed()\n    {\n        _mainLayout.RunNotification(new Notification(\"File upload failed.\", NotificationType.Fail));\n    }\n\n    public async Task OnClose()\n    {\n        await _js.InvokeVoidAsync(\"detachCardPasteHandler\");\n\n        Dispose();\n    }\n\n    public override void Dispose()\n    {\n        if (_pasteObjRef is not null)\n        {\n            _pasteObjRef.Dispose();\n            _pasteObjRef = null;\n        }\n\n        if (_timer is not null)\n        {\n            _timer.Stop();\n            _timer.Dispose();\n            _timer = null;\n        }\n\n        base.Dispose();\n    }\n\n    private async Task CopyDeepLink()\n    {\n        if (_card is null)\n            return;\n\n        var deepLink = $\"{_navigationManager.BaseUri.TrimEnd('/')}/boards/{_card.Column.Board.Id}/{_card.Id}\";\n        await _js.InvokeVoidAsync(\"copyText\", deepLink);\n        _mainLayout.RunNotification(new Notification(\"Card link copied to clipboard.\"));\n    }\n\n    private async Task OnTextChanged(ChangeEventArgs e)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Name = e.Value?.ToString() ?? string.Empty;\n        card.Activities.Add(new Activity\n        {\n            Text = \"<b>changed</b> the title\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n    private void OnCommentTextChanged(ChangeEventArgs e)\n    {\n        _commentText = e.Value?.ToString() ?? string.Empty;\n    }\n\n    private async Task OnDescriptionChanged(ChangeEventArgs e)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Description = e.Value?.ToString() ?? string.Empty;\n        card.Activities.Add(new Activity\n        {\n            Text = \"<b>changed</b> the description\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n\n\n    private void UpdateTimer()\n    {\n        var targetRecord = _card?.TimeRecords?.FirstOrDefault(x => x.UserId.Equals(_user.Id) && x.EndedAt == null);\n\n        if(_card is null || targetRecord is null)\n        {\n            if (_timer is not null)\n            {\n                _timer.Stop();\n                _timer.Dispose();\n            }\n\n            return;\n        }\n\n        _ongoingTimer = DateTime.Now - targetRecord.StartedAt;\n        StateHasChanged();\n        \n        if (_timer is not null)\n        {\n            _timer.Stop();\n            _timer.Dispose();\n        }\n\n        _timer = new System.Timers.Timer(1000);\n        _timer.Elapsed += OnTimerTick;\n        _timer.AutoReset = true;\n        _timer.Start();\n    }\n\n    private async void OnTimerTick(object? sender, ElapsedEventArgs e)\n    {\n        _ongoingTimer = _ongoingTimer.Add(TimeSpan.FromSeconds(1));\n        await InvokeAsync(StateHasChanged);\n    }\n\n    private async Task PostComment()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Comments.Add(new Comment\n            {\n                Text = _commentText,\n                CreatedAt = DateTime.Now,\n                CreatedById = _user.Id,\n                CardId = _card.Id\n            });\n        card.Activities.Add(new Activity\n            {\n                Text = \"<b>posted</b> a comment\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _commentText = string.Empty;\n        await UpdateCard();\n    }\n\n    private async Task StartTimer()\n    {\n        if (_card is null)\n            return;\n\n        _ongoingTimer = TimeSpan.Zero;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.TimeRecords.Add(new TimeRecord\n        {\n            UserId = _user.Id,\n            CardId = card.Id,\n            StartedAt = DateTime.Now\n        });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n        UpdateTimer();\n    }\n\n    private async Task EndTimer(TimeRecord activeTimeRecord)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        var targetRecord = card.TimeRecords.FirstOrDefault(x => x.Id.Equals(activeTimeRecord.Id));\n\n        if(targetRecord is null)\n            return;\n\n        targetRecord.EndedAt = DateTime.Now;\n\n        if((targetRecord.EndedAt.Value - targetRecord.StartedAt).TotalSeconds < 1)\n        {\n            db.TimeRecords.Remove(targetRecord);\n        }\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n        UpdateTimer();\n    }\n\n    private async Task DeleteTimeRecord(TimeRecord timeRecord)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await db.TimeRecords.Where(x => x.Id.Equals(timeRecord.Id)).ExecuteDeleteAsync();\n\n        db.Activities.Add(new Activity\n        {\n            Text = $\"<b>deleted</b> time record of <b>{(timeRecord.EndedAt!.Value - timeRecord.StartedAt).ToElapsedString()}</b>\",\n            UserId = _user.Id,\n            CardId = _card.Id,\n        });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    private async Task MoveToPreviousList()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        var targetColumn = await db.Columns\n            .Include(x => x.Cards)\n            .Where(x => x.BoardId.Equals(card.Column.BoardId))\n            .FirstOrDefaultAsync(x => x.Index.Equals(card.Column.Index - 1));\n\n        if (targetColumn is null)\n            return;\n\n        card.Column = targetColumn;\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>moved</b> the card to <b>{targetColumn.Name}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n    private async Task Join()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        var targetUser = await db.Users.SingleOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if(targetUser is null)\n            return;\n\n        card.Assignees.Add(targetUser);\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>joined</b> the card\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n    private async Task Leave()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        var targetUser = await db.Users.SingleOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if (targetUser is null)\n            return;\n\n        card.Assignees.Remove(targetUser);\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>left</b> the card\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n    private async Task MoveToNextList()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        var targetColumn = await db.Columns\n            .Include(x => x.Cards)\n            .Where(x => x.BoardId.Equals(card.Column.BoardId))\n            .FirstOrDefaultAsync(x => x.Index.Equals(card.Column.Index + 1));\n\n        if (targetColumn is null)\n            return;\n\n        card.Column = targetColumn;\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>moved</b> the card to <b>{targetColumn.Name}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        await UpdateCard();\n    }\n\n    private async Task UpdateCard()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        _card = await GetNoTrackingCard(db, _card.Id);\n        await LoadSubtasksAsync();\n        StateHasChanged();\n\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async Task DownloadAttachment(Attachment attachment)\n    {\n        await _js.InvokeVoidAsync(\"triggerFileDownload\", attachment.OriginalName, $\"{Constants.Mappings.ATTACHMENTS_DOWNLOAD_PATH}/{attachment.FileName}\");\n    }\n\n    private async Task DeleteAttachment(Attachment attachment)\n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Attachments.RemoveAll(x => x.Id.Equals(attachment.Id));\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>deleted</b> file named <b>{attachment.OriginalName}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n                });\n\n        _mainLayout.RunNotification(new Notification($\"File {attachment.OriginalName} deleted successfully.\"));\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    private async Task DeleteReminder(Reminder reminder)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Reminders.RemoveAll(x => x.Id.Equals(reminder.Id));\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>deleted</b> the reminder at <b>{reminder.At.ToReadableStringWithTime()}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    private async Task DeleteDeadline()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.Deadline = null;\n        card.Activities.Add(new Activity\n            {\n                Text = \"<b>deleted</b> the deadline\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    private async Task OnSubtaskMoved((string movedItemId, string? targetItemId, string _) args)\n    {\n        if (_card is null)\n            return;\n\n        var movedSubtaskId = Convert.ToInt32(args.movedItemId);\n\n        if (_subtasks is null)\n            return;\n\n        var movedSubtask = _subtasks.FirstOrDefault(x => x.Id.Equals(movedSubtaskId));\n\n        if (movedSubtask is null)\n            return;\n\n        int? targetItemId = args.targetItemId is not null ? Convert.ToInt32(args.targetItemId) : null;\n        var targetIndex = ComputeReindexedListOrAdjustIndices(_subtasks, movedSubtaskId, targetItemId);\n        movedSubtask.Index = targetIndex;\n        IndexHelper.FixIndices(_subtasks);\n        StateHasChanged();\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n            var card = await db.Cards\n                .Include(x => x.Subtasks)\n                .FirstOrDefaultAsync(x => x.Id == _card.Id);\n\n            if (card is null)\n                throw new InvalidOperationException(\"Card not found in DB.\");\n\n            var dbMoved = card.Subtasks.FirstOrDefault(x => x.Id.Equals(movedSubtaskId));\n            if (dbMoved is null)\n                throw new InvalidOperationException(\"Moved subtask not found in DB.\");\n\n            var dbTargetIndex = ComputeReindexedListOrAdjustIndices(card.Subtasks, movedSubtaskId, targetItemId);\n            dbMoved.Index = dbTargetIndex;\n            IndexHelper.FixIndices(card.Subtasks);\n\n            await db.SaveChangesAsync();\n\n            await LoadSubtasksAsync();\n        }\n        catch (Exception ex)\n        {\n            _mainLayout.RunNotification(new Notification(\"Failed to move subtask.\", NotificationType.Fail));\n            _logger?.LogError(ex, \"Failed to move subtask\");\n            await UpdateCard();\n        }\n    }\n\n    private int ComputeReindexedListOrAdjustIndices(ICollection<Subtask> subtasks, int movedSubtaskId, int? targetItemId)\n    {\n        int defaultTarget = subtasks.Any() ? subtasks.Max(x => x.Index) + 1 : 0;\n\n        if (targetItemId.HasValue)\n        {\n            var target = subtasks.FirstOrDefault(x => x.Id == targetItemId.Value);\n            if (target is not null)\n            {\n                defaultTarget = target.Index;\n\n                foreach (var st in subtasks.OrderByDescending(x => x.Index))\n                {\n                    if (st.Index >= defaultTarget)\n                        st.Index++;\n                }\n            }\n        }\n\n        return defaultTarget;\n    }\n\n    private async Task DeleteLink(CardLink link)\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var targetLink = await db.CardLinks\n            .Include(x => x.CardOne)\n                .ThenInclude(x => x.Activities)\n            .Include(x => x.CardOne)\n                .ThenInclude(x => x.Column)\n                    .ThenInclude(x => x.Board)\n            .Include(x => x.CardTwo)\n                .ThenInclude(x => x.Column)\n                    .ThenInclude(x => x.Board)\n            .Include(x => x.CardTwo)\n                .ThenInclude(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(link.Id));\n\n        if (targetLink is null)\n            return;\n\n        var oppositeCategory = Constants.LINK_TYPE_PAIRS.ContainsKey(targetLink.Category) ? Constants.LINK_TYPE_PAIRS[targetLink.Category] : Constants.LINK_TYPE_PAIRS.First(x => x.Value.Equals(targetLink.Category)).Key;\n        var oppositeTarget = await db.CardLinks.FirstOrDefaultAsync(x => x.CardTwoId.Equals(targetLink.CardOneId));\n\n        if (oppositeTarget is not null)\n        {\n            db.CardLinks.Remove(oppositeTarget);\n\n            targetLink.CardTwo.Activities.Add(new Activity\n                {\n                    Text = $\"<b>deleted</b> a linked issue <b>{targetLink.CardOne.Column.Board.Code}-{targetLink.CardOne.Number}</b> with <b>{targetLink.Category}</b> relationship\",\n                    UserId = _user.Id,\n                    CardId = targetLink.CardTwoId,\n                });\n        }\n\n        db.CardLinks.Remove(targetLink);\n\n        targetLink.CardOne.Activities.Add(new Activity\n            {\n                Text = $\"<b>deleted</b> a linked issue <b>{targetLink.CardTwo.Column.Board.Code}-{targetLink.CardTwo.Number}</b> with <b>{targetLink.Category}</b> relationship\",\n                UserId = _user.Id,\n                CardId = targetLink.CardOneId,\n            });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    public async Task OnFileChanged(InputFileChangeEventArgs e)\n    {\n        if (_card is null)\n            return;\n\n        if(e.FileCount > Constants.Limits.MAX_FILES)\n        {\n            _mainLayout.RunNotification(new Notification($\"Only {Constants.Limits.MAX_FILES} can be uploaded.\", NotificationType.Fail));\n            return;\n        }\n\n        var files = e.GetMultipleFiles(Constants.Limits.MAX_FILES).ToList();\n\n        var folderPath = Constants.SAVE_UPLOADED_FILES_PATH;\n\n        if (!Directory.Exists(folderPath))\n            Directory.CreateDirectory(folderPath);\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        foreach (var file in files)\n        {\n            if (file.Size > Constants.Limits.MAX_FILE_SIZE)\n            {\n                _mainLayout.RunNotification(new Notification($\"The file {file.Name} is too large.\", NotificationType.Fail));\n                continue;\n            }\n\n            var cleanFileName = WebUtility.HtmlEncode(file.Name);\n\n            try\n            {\n                var extension = file.Name[(file.Name.LastIndexOf('.') + 1)..];\n\n                string path;\n                string trustedFileName;\n                do\n                {\n                    trustedFileName = Path.GetRandomFileName();\n                    trustedFileName = trustedFileName[..trustedFileName.LastIndexOf('.')] + $\".{extension}\";\n\n                    path = Path.Combine(folderPath, trustedFileName);\n                } while (File.Exists(path));\n\n                await using FileStream fs = new(path, FileMode.Create);\n                await file.OpenReadStream(Constants.Limits.MAX_FILE_SIZE).CopyToAsync(fs);\n\n                card.Attachments.Add(new Attachment\n                {\n                    CardId = _card.Id,\n                    FileName = trustedFileName,\n                    OriginalName = cleanFileName\n                });\n                card.Activities.Add(new Activity\n                    {\n                    Text = $\"<b>uploaded</b> file named <b>{cleanFileName}</b>\",\n                        UserId = _user.Id,\n                        CardId = card.Id,\n                });\n\n                await db.SaveChangesAsync();\n\n                _mainLayout.RunNotification(new Notification($\"File {cleanFileName} uploaded successfully.\"));\n            }\n            catch\n            {\n                _mainLayout.RunNotification(new Notification($\"File upload error while uploading {cleanFileName}.\", NotificationType.Fail));\n                continue;\n            }\n        }\n\n        await UpdateCard();\n    }\n\n    private async Task<Card?> GetNoTrackingCard(DataContext db, int id)\n    { \n        var card = await db.Cards\n            .AsNoTracking()\n            .Include(x => x.Column)\n                .ThenInclude(x => x.Board)\n                    .ThenInclude(x => x.Labels)\n            .Include(x => x.CreatedBy)\n            .Include(x => x.Comments)\n                .ThenInclude(x => x.CreatedBy)\n            .Include(x => x.Assignees)\n            .Include(x => x.Attachments)\n            .Include(x => x.Activities)\n                .ThenInclude(x => x.User)\n            .Include(x => x.Reminders)\n            .Include(x => x.Labels)\n            .Include(x => x.TimeRecords)\n                .ThenInclude(x => x.User)\n            .Include(x => x.LinkedIssuesOne)\n                .ThenInclude(x => x.CardTwo)\n                    .ThenInclude(x => x.Column)\n                        .ThenInclude(x => x.Board)\n                            .ThenInclude(x => x.Project)\n            .FirstOrDefaultAsync(x => x.Id.Equals(id));\n\n        if(card is not null)\n            _lastColumnIndex = await db.Columns.Where(x => x.BoardId.Equals(card.Column.BoardId)).Select(x => x.Index).MaxAsync();\n\n        return card;\n    }\n\n    private async Task<Card?> GetCard(DataContext db, int id)\n    {\n        var card = await db.Cards\n            .Include(x => x.Column)\n                .ThenInclude(x => x.Board)\n                    .ThenInclude(x => x.Labels)\n            .Include(x => x.CreatedBy)\n            .Include(x => x.Comments)\n                .ThenInclude(x => x.CreatedBy)\n            .Include(x => x.Assignees)\n            .Include(x => x.Attachments)\n            .Include(x => x.Activities)\n            .Include(x => x.Reminders)\n            .Include(x => x.Labels)\n            .Include(x => x.TimeRecords)\n                .ThenInclude(x => x.User)\n            .Include(x => x.LinkedIssuesOne)\n                .ThenInclude(x => x.CardTwo)\n                    .ThenInclude(x => x.Column)\n                        .ThenInclude(x => x.Board)\n                            .ThenInclude(x => x.Project)\n            .FirstOrDefaultAsync(x => x.Id.Equals(id));\n\n        if (card is not null)\n            _lastColumnIndex = await db.Columns.Where(x => x.BoardId.Equals(card.Column.BoardId)).Select(x => x.Index).MaxAsync();\n\n        return card;\n    }\n\n    private async Task LoadSubtasksAsync()\n    {\n        if (_card is null)\n            return;\n\n        int? scrollPos = null;\n\n        try\n        {\n            scrollPos = await _js.InvokeAsync<int?>(\"getElementScrollTop\", _scrollContainerRef);\n        }\n        catch\n        {\n        }\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n            _subtasks = await db.Subtasks\n                .Where(x => x.CardId == _card.Id)\n                .Include(x => x.Assignees)\n                .OrderBy(x => x.Index)\n                .ToListAsync();\n\n            await InvokeAsync(StateHasChanged);\n\n            if (scrollPos.HasValue)\n            {\n                try\n                {\n                    await _js.InvokeVoidAsync(\"setElementScrollTop\", _scrollContainerRef, scrollPos.Value);\n                }\n                catch\n                {\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            _subtasks = null;\n            await InvokeAsync(StateHasChanged);\n            _mainLayout.RunNotification(new Notification(\"Failed to load subtasks.\", NotificationType.Fail));\n            _logger.LogError(ex, \"Failed to load subtasks for card {CardId}\", _card.Id);\n        }\n    }\n\n    private async Task UnsnoozeCard()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.SnoozedUntil = null;\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>unsnoozed</b> this card\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n\n    private async Task RemoveRepeat()\n    {\n        if (_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await GetCard(db, _card.Id);\n\n        if (card is null)\n            return;\n\n        card.RepeatInfo = null;\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>turned repeating off</b> for this card\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n        await UpdateCard();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditColumnModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"Edit column\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    @if (_column is not null)\n    {\n        <EditForm class=\"form\" EditContext=\"  _editContext\">\n            <DataAnnotationsValidator />\n            \n            <div class=\"form-group\">\n                <Name For=\" () => _column.Name\" />\n                <InputText class=\"form-control\" @bind-Value=\"_column.Name\" @ref=\"FocusElement\" />\n                <ValidationMessage For=\"() => _column.Name\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _column.MaxCards\" />\n                <InputNumber class=\"form-control\" @bind-Value=\"_column.MaxCards\" />\n                <ValidationMessage For=\"() => _column.MaxCards\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _column.Finished\" />\n                <InputCheckbox class=\"switch\" @bind-Value=\"_column.Finished\" />\n                <ValidationMessage For=\"() => _column.Finished\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _column.NewCardPlacement\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_column.NewCardPlacement\">\n                    @foreach (Enum enumValue in Enum.GetValues<CardPlacement>())\n                    {\n                        <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _column.NewCardPlacement\" />\n            </div>\n        </EditForm>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Column? _column;\n\n    private EditContext? _editContext;\n\n    public async Task Open(int columnId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n        _column = await db.Columns\n            .AsNoTracking()\n            .FirstOrDefaultAsync(x => x.Id.Equals(columnId));\n\n        if (_column is null)\n            return;\n\n        _editContext = new EditContext(_column);\n\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if (Modal is null || _editContext is null || _column is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var targetColumn = await db.Columns\n            .FirstOrDefaultAsync(x => x.Id.Equals(_column.Id));\n\n        if (targetColumn is not null)\n        {\n            targetColumn.Name = _column.Name;\n            targetColumn.Finished = _column.Finished;\n            targetColumn.MaxCards = _column.MaxCards;\n            targetColumn.NewCardPlacement = _column.NewCardPlacement;\n\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditDeadlineModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Set deadline\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_deadlineModel\" OnValidSubmit=\"SetDeadline\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _deadlineModel.At\" />\n                <InputDate class=\"form-control\" @bind-Value=\"_deadlineModel.At\" min=\"@DateTime.Today.ToHtmlDateString()\" />\n                <ValidationMessage For=\"() => _deadlineModel.At\" />\n            </div>\n            <div class=\"form-group\">\n                <Name For=\"() => _deadlineModel.Time\" />\n                <TimeSelect @bind-Value=\"_deadlineModel.Time\" />\n                <ValidationMessage For=\"() => _deadlineModel.Time\" />\n            </div>\n\n            <button type=\"submit\">Set</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private DeadlineModel _deadlineModel = new();\n\n    public void Open(ElementReference? triggerElement, Card card) {\n        _card = card;\n        _deadlineModel = new()\n            {\n                At = card.Deadline ?? DateTime.Today,\n                Time = (card.Deadline ?? DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute)).ToString(\"HH:mm\")\n            };\n        _modalRef?.Open(triggerElement);\n        StateHasChanged();\n    }\n\n    public async Task SetDeadline() \n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var time = DateTime.ParseExact(_deadlineModel.Time, \"HH:mm\", null);\n\n        card.Deadline = new DateTime(_deadlineModel.At.Year, _deadlineModel.At.Month, _deadlineModel.At.Day, time.Hour, time.Minute, 0);\n        card.DeadlineProcessed = false;\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>set</b> the deadline for <b>{card.Deadline.Value.ToReadableStringWithTime()}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditLabelModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=Modal Title=\"Edit label\" OnSubmitAttempted=\"EditLabel\">\n    @if(_board is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" EditContext=\"_editContext\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.Text\" />\n                <input type=\"text\" class=\"form-control\" value=\"@_labelModel.Text\" @oninput=\"OnTextUpdated\" @ref=\"FocusElement\" />\n                <ValidationMessage For=\"() => _labelModel.Text\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.TextColor\" />\n                <input type=\"color\" value=\"@(_labelModel.TextColor.HasValue ? ColorTranslator.ToHtml(_labelModel.TextColor.Value) : string.Empty)\" @onchange=\"OnTextColorUpdated\" />\n                <ValidationMessage For=\"() => _labelModel.TextColor\" />\n            </div>\n\n            <div class=\"form-group\">\n                <Name For=\"() => _labelModel.BackgroundColor\" />\n                <input type=\"color\" value=\"@(_labelModel.BackgroundColor.HasValue ? ColorTranslator.ToHtml(_labelModel.BackgroundColor.Value) : string.Empty)\" @onchange=\"OnBackgroundColorUpdated\" />\n                <ValidationMessage For=\"() => _labelModel.BackgroundColor\" />\n            </div>\n\n            <div class=\"form-group\">\n                <label>Preview:</label>\n                <LabelView Label=\"_showcaseLabel\"/>\n            </div>\n        </EditForm>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Board? _board;\n    private Label? _label;\n    private LabelModel _labelModel = new();\n    private Label? _showcaseLabel;\n    private EditContext? _editContext;\n\n    public void Open(Board board, Label label) {\n        _board = board;\n        _label = label;\n        _labelModel = new()\n        {\n            Text = label.Name,\n            BackgroundColor = label.BackgroundColor,\n            TextColor = label.TextColor\n        };\n        _showcaseLabel = new()\n            {\n                BoardId = 0,\n                Name = label.Name,\n                BackgroundColor = label.BackgroundColor,\n                TextColor = label.TextColor\n            };\n        _editContext = new EditContext(_board);\n\n        base.Open();\n    }\n\n    private void OnTextUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        if(string.IsNullOrWhiteSpace(str))\n        {\n            _showcaseLabel.Name = \"Example\";\n            return;\n        }\n\n        _showcaseLabel.Name = str;\n        _labelModel.Text = str;\n    }\n\n    private void OnTextColorUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        _showcaseLabel.TextColor = ColorTranslator.FromHtml(str);\n        _labelModel.TextColor = _showcaseLabel.TextColor;\n    }\n\n    private void OnBackgroundColorUpdated(ChangeEventArgs e)\n    {\n        if (e.Value is not string str || _showcaseLabel is null)\n            return;\n\n        _showcaseLabel.BackgroundColor = ColorTranslator.FromHtml(str);\n        _labelModel.BackgroundColor = _showcaseLabel.BackgroundColor;\n    }\n\n    public async Task EditLabel() \n    {\n        if(_board is null || _label is null || _editContext is null || !_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var board = await db.Boards\n            .Include(x => x.Labels)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if(board is null)\n            return;\n\n        var targetLabel = board.Labels.FirstOrDefault(x => x.Id.Equals(_label.Id));\n\n        if (targetLabel is null)\n            return;\n\n        targetLabel.BoardId = board.Id;\n        targetLabel.Name = _labelModel.Text;\n        targetLabel.TextColor = _labelModel.TextColor!.Value;\n        targetLabel.BackgroundColor = _labelModel.BackgroundColor!.Value;\n\n        await db.SaveChangesAsync();\n\n        _board = board;\n        StateHasChanged();\n        await OnSubmit.InvokeAsync();\n        Modal?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditProjectMembershipsModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=@($\"Edit memberships for project {_project?.Name}\") DisableButtons=\"true\" EnableTitle=\"true\">\n    @if(_project is null)\n    {\n        <Spinner/>\n    } else\n    {\n        <div class=\"flex flex-col items-center gap-3\">\n            <div class=\"flex w-full flex-row items-center gap-3\">\n                <input class=\"w-full rounded-lg bg-search-bar px-2 py-1 text-sm\" type=\"text\"\n                       placeholder=\"Enter e-mail address\" @oninput=\"OnInviteTextChanged\" @ref=\"FocusElement\" />\n                <button class=\"px-3 py-1.5\" @onclick=\"AddAccess\">Add</button>\n            </div>\n\n            <table class=\"border-separate border-spacing-x-5 border-spacing-y-1\">\n                @{\n                    var i = 0;\n                }\n                @foreach(var membership in _project.Memberships.OrderByDescending(x => x.IsAdmin).ThenBy(x => x.AddedAt))\n                {\n                    string avatarId = $\"avatar_{i}\";\n\n                    <tr class=\"text-sm\">\n                        <td>\n                            <div id=\"@avatarId\" @onclick=\"() => _mainLayout.UserInfoModal?.Open(avatarId, membership.UserId)\" class=\"avatar\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@membership.User.ProfilePictureFileName');\"></div>\n                        </td>\n                        <td>\n                            @membership.User.DisplayName @(membership.UserId.Equals(_user.Id) ? \"(you)\" : string.Empty)\n                        </td>\n                        <td>\n                            \n                            <Dropdown Disabled=\"@membership.UserId.Equals(_user.Id)\" Actions='new() {\n                                { \"Admin\", () => ChangeAdmin(membership.Id, true)},\n                                { \"Member\", () => ChangeAdmin(membership.Id, false)}\n                            }'>\n                        <div class='flex flex-row items-center justify-between pr-2 pl-5 transition-all ease-in-out @(!membership.UserId.Equals(_user.Id) ? \"bg-full-dropdown hover:bg-full-dropdown-hover cursor-pointer\" : \"bg-full-dropdown-disabled cursor-not-allowed\")'>\n                                    @(membership.IsAdmin ? \"Admin\" : \"Member\")\n                            <i class='fa fa-chevron-down edit-icon @(membership.UserId.Equals(_user.Id) ? \"!text-disabled-icon !hover:text-disabled-icon !cursor-not-allowed\" : string.Empty)' title=\"Change role\"></i>\n                                </div>\n                            </Dropdown>\n                        </td>\n                        <td>\n                            <i @onclick=\"() => RemoveUser(membership.UserId)\"\n                       class='fa fa-trash edit-icon @(membership.UserId.Equals(_user.Id) ? \"!text-disabled-icon !hover:text-disabled-icon !cursor-not-allowed\" : string.Empty)' title=\"Remove member\">\n                            </i>\n                        </td>\n                    </tr>\n\n                    i++;\n                }\n            </table>\n        </div>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private Project? _project;\n    private string _inviteText = string.Empty;\n\n    public async void Open(int projectId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _project = await db.Projects\n            .AsNoTracking()\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(projectId));\n\n        if (_project is null)\n            return;\n\n        StateHasChanged();\n\n        base.Open();\n    }\n\n    private void OnInviteTextChanged(ChangeEventArgs e) \n    {\n        _inviteText = e.Value?.ToString() ?? string.Empty;\n    }\n\n    private async Task AddAccess() \n    {\n        if(_project is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var project = await db.Projects\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_project.Id));\n\n        if (project is null)\n            return;\n\n        var targetUser = await db.Users.\n            FirstOrDefaultAsync(x => x.Email != null && x.Email.Equals(_inviteText));\n\n        if(targetUser is null)\n        {\n            _mainLayout.RunNotification(new Notification(\"There is no user with the provided e-mail address.\", NotificationType.Fail));\n            return;\n        }\n\n        if(project.Memberships.Any(x => x.UserId.Equals(targetUser.Id)))\n        {\n            _mainLayout.RunNotification(new Notification(\"This user already has access to this project.\", NotificationType.Fail));\n            return;\n        }\n\n        var membership = new ProjectMembership\n        {\n            ProjectId = project.Id,\n            IsAdmin = false,\n            UserId = targetUser.Id,\n            AddedAt = DateTime.Now\n        };\n\n        project.Memberships.Add(membership);\n        await db.SaveChangesAsync();\n\n        _project = project;\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async void ChangeAdmin(int membershipId, bool value)\n    {\n        if (_project is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var targetMembership = await db.ProjectMemberships.FirstOrDefaultAsync(x => x.Id.Equals(membershipId));\n\n        if (targetMembership is null)\n            return;\n\n        targetMembership.IsAdmin = value;\n        await db.SaveChangesAsync();\n\n        _project.Memberships.First(x => x.Id.Equals(membershipId)).IsAdmin = value;\n        await OnSubmit.InvokeAsync();\n    }\n\n    private async Task RemoveUser(int userId)\n    {\n        if (_project is null || userId.Equals(_user.Id))\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var project = await db.Projects\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_project.Id));\n\n        if (project is null)\n            return;\n\n        var targetMembership = project.Memberships.FirstOrDefault(x => x.UserId.Equals(userId));\n\n        if(targetMembership is null)\n            return;\n\n        project.Memberships.Remove(targetMembership);\n        await db.SaveChangesAsync();\n\n        _project = project;\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditProjectModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<Modal @ref=\"Modal\" Title=\"Edit project\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    @if(_project is null)\n    {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form\" EditContext=\"_editContext\">\n            <DataAnnotationsValidator/>\n            \n            <div class=\"form-group\">\n                <Name For=\"() => _project.Name\"/>\n                <InputText class=\"form-control\" @bind-Value=\"_project.Name\" @ref=\"FocusElement\" />\n                <ValidationMessage For=\"() => _project.Name\" />\n            </div>\n        </EditForm>\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    public Project? _project;\n\n    private EditContext? _editContext;\n\n    public async Task Open(int projectId)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _project = await db.Projects.AsNoTracking().FirstOrDefaultAsync(x => x.Id.Equals(projectId));\n\n        if (_project is null)\n            return;\n\n        _editContext = new EditContext(_project);\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if(Modal is null || _editContext is null || _project is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var project = await db.Projects.FirstOrDefaultAsync(x => x.Id.Equals(_project.Id));\n\n        if (project is not null)\n        {\n            project.Name = _project.Name;\n            await db.SaveChangesAsync();\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditSubtaskModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Edit subtask\">\n    @if(_subtask is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_subtaskModel\" OnValidSubmit=\"EditSubtask\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _subtaskModel.Text\" />\n                <InputText class=\"form-control\" @bind-Value=\"_subtaskModel.Text\" />\n                <ValidationMessage For=\"() => _subtaskModel.Text\" />\n            </div>\n\n            <button type=\"submit\">Add</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private Subtask? _subtask;\n\n    private SubtaskModel _subtaskModel = new();\n\n    public void Open(string triggerElementId, Subtask subtask) {\n        _subtaskModel = new()\n        {\n            Text = subtask.Text\n        };\n        _subtask = subtask;\n        StateHasChanged();\n        _modalRef?.Open(triggerElementId);\n    }\n\n    public async Task EditSubtask() \n    {\n        if(_subtask is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var subtask = await db.Subtasks\n            .Include(x => x.Card)\n                .ThenInclude(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_subtask.Id));\n\n        if(subtask is null)\n            return;\n\n        subtask.Card.Activities.Add(new Activity\n            {\n                Text = $\"<b>edited</b> subtask <b>{subtask.Text}</b> to <b>{_subtaskModel.Text}</b>\",\n                UserId = _user.Id,\n                CardId = subtask.CardId,\n            });\n        subtask.Text = _subtaskModel.Text;\n\n        await db.SaveChangesAsync();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditTimeRecordModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Edit time record\">\n    @if(_timeRecord is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_timeRecordModel\" OnValidSubmit=\"EditTimeRecord\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _timeRecordModel.Time\" />\n                <InputText class=\"form-control\" @bind-Value=\"_timeRecordModel.Time\"  />\n                <ValidationMessage For=\"() => _timeRecordModel.Time\" />\n            </div>\n\n            <button type=\"submit\">Edit</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private TimeRecord? _timeRecord;\n\n    private TimeRecordModel _timeRecordModel = new();\n\n    private string _oldTimeRecord = string.Empty;\n\n    public void Open(string triggerElementId, TimeRecord timeRecord) {\n        _timeRecord = timeRecord;\n        _timeRecordModel = new()\n            {\n                Time = (timeRecord.EndedAt!.Value - timeRecord.StartedAt).ConvertToString()\n            };\n        _oldTimeRecord = _timeRecordModel.Time;\n        _modalRef?.Open(triggerElementId);\n        StateHasChanged();\n    }\n\n    public async Task EditTimeRecord() \n    {\n        if(_timeRecord is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var timeRecord = await db.TimeRecords\n            .Include(x => x.Card)\n                .ThenInclude(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_timeRecord.Id));\n\n        if (timeRecord is null)\n            return;\n        \n        var timeSpan = _timeRecordModel.Time.ConvertToTimeSpan();\n\n        timeRecord.EndedAt = DateTime.Now;\n        timeRecord.StartedAt = DateTime.Now.Subtract(timeSpan).Subtract(TimeSpan.FromSeconds(1));\n\n        timeRecord.Card.Activities.Add(new Activity\n            {\n                Text = $\"<b>changed</b> the time record from <b>{_oldTimeRecord}</b> to <b>{_timeRecordModel.Time}</b>\",\n                UserId = _user.Id,\n                CardId = timeRecord.CardId,\n            });\n\n        await db.SaveChangesAsync();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/EditUserModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject UserManager<User> _userManager\n\n<Modal @ref=Modal Title=\"Edit user\" OnSubmitAttempted=\"EditUser\">\n    <EditForm class=\"form p-2\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator />\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.DisplayName\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.DisplayName\" @ref=FocusElement />\n            <ValidationMessage For=\"() => _userModel.DisplayName\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.Email\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.Email\" />\n            <ValidationMessage For=\"() => _userModel.Email\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.Password\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.Password\" />\n            <ValidationMessage For=\"() => _userModel.Password\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _userModel.ConfirmPassword\" />\n            <InputText class=\"form-control\" @bind-Value=\"_userModel.ConfirmPassword\" />\n            <ValidationMessage For=\"() => _userModel.ConfirmPassword\" />\n        </div>\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private User? _targetUser;\n    private UserModel _userModel = new();\n    private EditContext? _editContext;\n    private ValidationMessageStore? _validationMessageStore;\n\n    public async void Open(int userId) \n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _targetUser = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(userId));\n\n        ArgumentNullException.ThrowIfNull(_targetUser);\n\n        _userModel = new() \n        {\n            DisplayName = _targetUser.DisplayName,\n            Email = _targetUser.Email!\n        };\n\n        _editContext = new EditContext(_userModel);\n        _editContext.OnValidationRequested += (sender, args) =>\n        {\n            _validationMessageStore?.Clear();\n        };\n        _validationMessageStore = new(_editContext);\n\n        base.Open();\n    }\n\n    public async Task EditUser() \n    {\n        if(_targetUser is null || _editContext is null || !_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var targetUser = await _userManager.FindByIdAsync(_targetUser.Id.ToString());\n\n        ArgumentNullException.ThrowIfNull(targetUser);\n\n        var result = await _userManager.ResetPasswordAsync(targetUser, await _userManager.GeneratePasswordResetTokenAsync(targetUser), _userModel.Password);\n\n        if(!result.Succeeded)\n        {\n            foreach (var error in result.Errors)\n                _validationMessageStore?.Add(() => _userModel.Email, error.Description);\n\n            _editContext?.NotifyValidationStateChanged();\n            return;\n        }\n\n        targetUser.NeedsNewCredentials = true;\n        targetUser.Email = _userModel.Email;\n        targetUser.DisplayName = _userModel.DisplayName;\n\n        await _userManager.UpdateAsync(targetUser);\n\n        StateHasChanged();\n        await OnSubmit.InvokeAsync();\n        Modal?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/FilterCardsModal.razor",
    "content": "@implements IDisposable\n\n<ActionModal @ref=_modalRef Title=\"Filter cards\">\n    <div class=\"form p-2\">\n        <div class=\"form-group\">\n            <label for=\"text\">Text, description or card code</label>\n            <input value=\"@Model.Text\" id=\"text\" class=\"form-control\" @oninput=\"OnSearchChanged\"/>\n        </div>\n\n        <div class=\"form-group\">\n            <div class=\"flex flex-row items-center gap-1 text-xs\">\n                <label>Completion</label>\n            </div>\n            <div class=\"flex flex-col gap-1\">\n                <div class=\"flex w-72 cursor-pointer flex-row items-center gap-5 rounded px-2 py-1 text-sm transition-all ease-in-out select-none hover:bg-dropdown-option\" @onclick=\"ToggleExcludeCompleted\">\n                    <span class=\"font-bold\">Exclude completed cards</span>\n                    <i class='fa fa-check icon ml-auto @(Model.ExcludeCompleted ? string.Empty : \"opacity-0\")'></i>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"form-group\">\n            <div class=\"flex flex-row items-center gap-1 text-xs\">\n                <label>Assigned users</label>\n\n                @if (BoardMembers.Count > 2)\n                {\n                    if (Model.ExpandAssignedUsersSection)\n                    {\n                        <i class=\"fa fa-chevron-down edit-icon\" @onclick=\"SwitchUserAssignedCollapse\" title=\"Collapse\"></i>\n                    }\n\n                    else\n                    {\n                        <i class=\"fa fa-chevron-up edit-icon\" @onclick=\"SwitchUserAssignedCollapse\" title=\"Expand\"></i>\n                    }\n                }\n            </div>\n            <div class=\"flex flex-col gap-1\">\n                <div class=\"flex w-72 cursor-pointer flex-row items-center gap-5 rounded px-2 py-1 text-sm transition-all ease-in-out select-none hover:bg-dropdown-option\" @onclick=\"ToggleUnassignedFilter\">\n                    <div class=\"avatar mr-auto\"></div>\n                    <label class=\"cursor-pointer\">No assignee</label>\n                    <i class='fa fa-check icon ml-auto @(Model.IncludeUnassigned ? string.Empty : \"opacity-0\")'></i>\n                </div>\n                @foreach (var member in Model.ExpandAssignedUsersSection ? BoardMembers : BoardMembers.Take(2))\n                {\n                    <div class=\"flex w-72 cursor-pointer flex-row items-center gap-5 rounded px-2 py-1 text-sm transition-all ease-in-out select-none hover:bg-dropdown-option\" @onclick=\"() => ToggleUserFilter(member.Id)\">\n                        <div class=\"avatar mr-auto\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@member.ProfilePictureFileName');\"></div>\n                        <label class=\"cursor-pointer\">@member.DisplayName</label>\n                        <i class='fa fa-check icon ml-auto @(Model.AssignedUserIds.Contains(member.Id) ? string.Empty : \"opacity-0\")'></i>\n                    </div>\n                }\n            </div>\n        </div>\n\n        <div class=\"form-group\">\n            <div class=\"flex flex-row items-center gap-1 text-xs\">\n                <label>Labels</label>\n\n                @if (BoardLabels.Count > 3)\n                {\n                    if (Model.ExpandLabelsSection)\n                    {\n                        <i class=\"fa fa-chevron-down edit-icon\" @onclick=\"SwitchLabelsCollapse\" title=\"Collapse\"></i>\n                    }\n\n                    else\n                    {\n                        <i class=\"fa fa-chevron-up edit-icon\" @onclick=\"SwitchLabelsCollapse\" title=\"Expand\"></i>\n                    }\n                }\n            </div>\n            <div class=\"flex flex-col gap-1\">\n                @if (BoardLabels != null && BoardLabels.Any())\n                {\n                    @foreach (var label in Model.ExpandLabelsSection ? BoardLabels : BoardLabels.Take(3))\n                    {\n                        <div class=\"priority-selector-item cursor-pointer\" @onclick=\"() => ToggleLabelFilter(label.Id)\">\n                            <LabelView Label=\"label\" />\n                            @if (Model.LabelIds.Contains(label.Id))\n                            {\n                                <i class=\"fa fa-check text-add-outline\" title=\"Selected\"></i>\n                            }\n                        </div>\n                    }\n                }\n                else\n                {\n                    <div class=\"text-xs text-gray-500\">No labels available.</div>\n                }\n            </div>\n        </div>\n\n        <button type=\"button\" @onclick=\"ResetFilters\">Reset filters</button>\n    </div>\n</ActionModal>\n\n@code {\n    [Parameter]\n    public EventCallback SearchUpdated { get; set; }\n\n    [Parameter]\n    public required FilterCardsModel Model { get; set; }\n\n    [Parameter]\n    public required List<User> BoardMembers { get; set; } = [];\n\n    [Parameter]\n    public required List<Label> BoardLabels { get; set; } = [];\n\n    private async Task ToggleLabelFilter(int labelId)\n    {\n        if (Model.LabelIds.Contains(labelId))\n            Model.LabelIds.Remove(labelId);\n        else\n            Model.LabelIds.Add(labelId);\n        await SearchUpdated.InvokeAsync();\n    }\n\n    private ActionModal? _modalRef;\n    private System.Timers.Timer _debounceTimer = new System.Timers.Timer(Constants.Limits.DEBOUNCE_TIME_IN_MS);\n\n    public void Open(string triggerElementId) \n    {\n        _modalRef?.Open(triggerElementId);\n        StateHasChanged();\n    }\n\n    protected override void OnInitialized()\n    {\n        _debounceTimer.Elapsed += async (_, __) =>\n        {\n            await InvokeAsync(async () => await SearchUpdated.InvokeAsync());\n        };\n        _debounceTimer.AutoReset = false;\n    }\n\n    private async Task SwitchUserAssignedCollapse()\n    {\n        Model.ExpandAssignedUsersSection = !Model.ExpandAssignedUsersSection;\n        StateHasChanged();\n        await Task.Delay(1);\n        await _modalRef!.OnResized();\n    }\n\n    private async Task SwitchLabelsCollapse()\n    {\n        Model.ExpandLabelsSection = !Model.ExpandLabelsSection;\n        StateHasChanged();\n        await Task.Delay(1);\n        await _modalRef!.OnResized();\n    }\n\n    private void OnSearchChanged(ChangeEventArgs e)\n    {\n        Model.Text = e.Value?.ToString() ?? string.Empty;\n\n        _debounceTimer.Stop();\n        _debounceTimer.Start();\n    }\n\n    private async Task ResetFilters()\n    {\n        Model.ClearFilters();\n        await SearchUpdated.InvokeAsync();\n    }\n\n    private async Task ToggleUserFilter(int userId)\n    {\n        if (Model.AssignedUserIds.Contains(userId))\n            Model.AssignedUserIds.Remove(userId);\n        else\n            Model.AssignedUserIds.Add(userId);\n        await SearchUpdated.InvokeAsync();\n    }\n\n    private async Task ToggleUnassignedFilter()\n    {\n        Model.IncludeUnassigned = !Model.IncludeUnassigned;\n        await SearchUpdated.InvokeAsync();\n    }\n\n    private async Task ToggleExcludeCompleted()\n    {\n        Model.ExcludeCompleted = !Model.ExcludeCompleted;\n        await SearchUpdated.InvokeAsync();\n    }\n\n    public void Dispose()\n    {\n        _debounceTimer.Stop();\n        _debounceTimer.Dispose();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/ImportModal.razor",
    "content": "@using System.Text.Json\n@inherits AbstractModal\n@inject ILogger<ImportModal> _logger\n@inject TrelloImportService _trelloImportService\n\n<Modal @ref=\"Modal\" Title=\"Import board\" OnSubmitAttempted=\"OnSubmitAttempted\">\n    <EditForm class=\"form\" EditContext=\"_editContext\">\n        <DataAnnotationsValidator />\n\n        <div class=\"form-group\">\n            <Name For=\"() => _model.Source\" />\n            <InputSelect class=\"form-control\" @bind-Value=\"_model.Source\">\n                @foreach (Enum enumValue in Enum.GetValues(typeof(ImportSource)))\n                {\n                    if (_model.Source.Equals(enumValue))\n                    {\n                        <option selected value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                    }\n                    else\n                    {\n                        <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                    }\n                }\n            </InputSelect>\n            <ValidationMessage For=\"() => _model.Source\" />\n        </div>\n\n        <div class=\"form-group\">\n            <Name For=\"() => _model.Code\" />\n            <InputText class=\"form-control\" @bind-Value=\"_model.Code\" />\n            <ValidationMessage For=\"() => _model.Code\" />\n        </div>\n\n        <div class=\"form-group flex flex-col items-center\">\n            <InputFile class=\"hidden\" id=\"file-upload\" OnChange=\"OnFileChanged\" />\n            <label for=\"file-upload\" class=\"board-card-create\">\n                @if (_isLoading)\n                {\n                    <Spinner/>\n                } else {\n                    <i class=\"fa fa-upload text-3xl\" title=\"Upload JSON file\"></i>\n                    <div>Upload JSON</div>\n                }\n            </label>\n            @if(_model.ImportDto is not null) \n            {\n                <div>Loaded board named @_model.ImportDto.Name with @_model.ImportDto.Lists.Count columns, @_model.ImportDto.Cards.Count cards and @_model.ImportDto.Members.Count members.</div>\n            }\n            <ValidationMessage For=\"() => _model.ImportDto\" />\n        </div>\n\n        @if(_model.ImportDto is not null && _model.MemberIdentifiers is not null)\n        {\n            <div class=\"form-group\">\n                <Name For=\"() => _model.ArchivedCardsHandling\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_model.ArchivedCardsHandling\">\n                    @foreach (Enum enumValue in Enum.GetValues(typeof(TrelloArchivedHandlingType)))\n                    {\n                        if (_model.ArchivedCardsHandling.Equals(enumValue))\n                        {\n                            <option selected value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                        else\n                        {\n                            <option value=\"@enumValue\">@enumValue.GetDisplayName()</option>\n                        }\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _model.ArchivedCardsHandling\" />\n            </div>\n\n            <p>\n                We have detected the following members (by their username) in your import file. <br/>\n                Please provide e-mail addresses/full names they are using in Ticky so we can assign them to the imported cards (this will not grant them access to the board). <br/>\n                If the e-mail/full name is not found, it will be ignored instead of showing an error due to privacy concerns.\n            </p>\n            @foreach (var i in Enumerable.Range(0, _model.MemberIdentifiers.Count()))\n            {\n                var member = _model.ImportDto.Members[i];\n                <div class=\"form-group\">\n                    <label>@member.FullName (@member.Username)</label>\n                    <InputText class=\"form-control\" @bind-Value=\"_model.MemberIdentifiers[i]\" />\n                </div>\n            }\n        }\n    </EditForm>\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnSubmit { get; set; }\n\n    private ImportModel _model = new();\n    private EditContext? _editContext;\n    private int _projectId;\n\n    private bool _isLoading;\n\n    public void Open(int projectId)\n    {\n        _projectId = projectId;\n\n        _model = new();\n        _editContext = new EditContext(_model);\n\n        base.Open();\n    }\n\n    private async Task OnSubmitAttempted()\n    {\n        if (Modal is null || _editContext is null)\n            return;\n\n        if (!_editContext.Validate())\n            return;\n\n        try\n        {\n            await _trelloImportService.ImportTrelloBoardAsync(_model, _projectId, _user.Id);\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError($\"Import failed, error: {ex}\");\n            ShowUploadError(\"An error occurred while importing the board. Please check the logs and open a GitHub issue if necessary.\");\n            return;\n        }\n\n        await Modal.Close();\n        await OnSubmit.InvokeAsync();\n    }\n\n    private void ShowUploadError(string message)\n    {\n        _isLoading = false;\n        _mainLayout.RunNotification(new Notification($\"File upload failed: {message}\", NotificationType.Fail));\n        StateHasChanged();\n    }\n\n    public async Task OnFileChanged(InputFileChangeEventArgs e)\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n        _isLoading = true;\n\n        if (!e.File.ContentType.Contains(\"application/json\"))\n        {\n            ShowUploadError(\"The file must be a JSON file.\");\n            return;\n        }\n\n        if (e.File.Size > Constants.Limits.MAX_JSON_SIZE)\n        {\n            ShowUploadError(\"The file is too large.\");\n            return;\n        }\n\n        try\n        {\n            using var stream = e.File.OpenReadStream(Constants.Limits.MAX_JSON_SIZE);\n            _model.ImportDto = await JsonSerializer.DeserializeAsync<TrelloImportDTO>(stream);\n\n            if(_model.ImportDto is null)\n            {\n                ShowUploadError(\"Invalid import format. Confirm you uploaded the correct file, if so, open a GitHub issue, the format may have changed.\");\n                return;\n            }\n            \n            _model.MemberIdentifiers = new string[_model.ImportDto.Members.Count];\n\n            _mainLayout.RunNotification(new Notification(\"File was uploaded, you can verify the data and confirm the import.\"));\n            _isLoading = false;\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError($\"File upload failed, file name {e.File.Name}, error: {ex}\");\n            ShowUploadError(\"An error occured. Please take a look at the application logs and open a GitHub issue.\");\n        }\n\n        StateHasChanged();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/InformationModal.razor",
    "content": "@inherits AbstractModal\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject InformationService _informationService\n\n<Modal @ref=\"Modal\" Title=@_title SubmitButtonText=\"Acknowledge\" CancelButtonText=\"Later\" OnSubmitAttempted=\"OnAcknowledged\" OnCancel=\"OnSnooze\">\n    @((MarkupString)_message)\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    private string _title = string.Empty;\n    private string _message = string.Empty;\n    private int? _infoId;\n\n    public async Task OpenIfNeeded()\n    {\n        if (Modal is null)\n            return;\n\n        var unseenInformation = _informationService.Information;\n\n        if(_user.LastViewedInformation.HasValue)\n            unseenInformation = unseenInformation.Where(x => _user.LastViewedInformation.Value < x.Id).ToList();\n\n        if(!unseenInformation.Any() || (_user.InformationSnoozeUntil.HasValue && _user.InformationSnoozeUntil.Value > DateTime.Now))\n            return;\n\n        var targetInformation = unseenInformation.OrderBy(x => x.Id).First();\n\n        _title = targetInformation.Title;\n        _message = targetInformation.Message;\n        _infoId = targetInformation.Id;\n\n        await Modal.Show();\n    }\n\n    public async Task OnAcknowledged()\n    {\n        ArgumentNullException.ThrowIfNull(_infoId);\n        ArgumentNullException.ThrowIfNull(Modal);\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await db.Users.Where(x => x.Id == _user.Id).ExecuteUpdateAsync(x => x.SetProperty(u => u.LastViewedInformation, _infoId));\n        await Modal.Close();\n    }\n\n    public async Task OnSnooze()\n    {\n        ArgumentNullException.ThrowIfNull(_infoId);\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await db.Users.Where(x => x.Id == _user.Id).ExecuteUpdateAsync(x => x.SetProperty(u => u.InformationSnoozeUntil, DateTime.Now.AddDays(1)));\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/LabelModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Labels\">\n    @if(_card is null || _labels is null) {\n        <Spinner/>\n    } else {\n        if (_labels.Any())\n        {\n            <div class=\"flex w-36 flex-col gap-1\">\n                @foreach (var label in _labels)\n                {\n                    <div class=\"priority-selector-item\" @onclick=\"() => OnSelect(label)\">\n                        <LabelView Label=\"label\"/>\n\n                        @if (_card.Labels.Any(x => x.Id.Equals(label.Id)))\n                        {\n                            <i class=\"fa fa-check text-add-outline\" title=\"Selected\"></i>\n                        }\n                    </div>\n                }\n            </div>\n        } else\n        {\n            <div>No labels have been created for this board. You can do so in the board settings.</div>\n        }\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private List<Label>? _labels;\n\n    public void Open(ElementReference? triggerElement, Card card, List<Label> labels) {\n        _card = card;\n        _labels = labels;\n        _modalRef?.Open(triggerElement);\n    }\n\n    public async Task OnSelect(Label label)\n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Activities)\n            .Include(x => x.Labels)\n            .Include(x => x.Column)\n                .ThenInclude(x => x.Board)\n                    .ThenInclude(x => x.Labels)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        if(card.Labels.Any(x => x.Id.Equals(label.Id)))\n        {\n            card.Labels.RemoveAll(x => x.Id.Equals(label.Id));\n            card.Activities.Add(new Activity\n                {\n                    Text = $\"<b>removed</b> label <b>{label.Name}</b>\",\n                    UserId = _user.Id,\n                    CardId = card.Id,\n                });\n        } else {\n            var targetLabel = await db.Labels.FirstOrDefaultAsync(x => x.Id.Equals(label.Id));\n\n            if(targetLabel is null)\n                return;\n\n            card.Labels.Add(targetLabel);\n            card.Activities.Add(new Activity\n                {\n                    Text = $\"<b>added</b> label <b>{label.Name}</b>\",\n                    UserId = _user.Id,\n                    CardId = card.Id,\n                });\n        }\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        await UpdateCard.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/LinkCardsModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject IJSRuntime _js\n\n<ActionModal @ref=_modalRef Title=\"Link card\">\n    @if(_card is null) \n    {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" EditContext=\"_editContext\" OnSubmit=\"OnSubmitAttempted\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _linkCardsModel.Text\" />\n                <InputSelect class=\"form-control\" @bind-Value=\"_linkCardsModel.Text\">\n                    @foreach(var item in Constants.LINK_TYPE_PAIRS.Keys)\n                    {\n                        <option value=\"@item\">@item</option>\n                    }\n                    @foreach (var item in Constants.LINK_TYPE_PAIRS.Values)\n                    {\n                        <option value=\"@item\">@item</option>\n                    }\n                </InputSelect>\n                <ValidationMessage For=\"() => _linkCardsModel.Text\" />\n                @if (_cardError is not null)\n                {\n                    <div class=\"validation-message\">@_cardError</div>\n                }\n            </div>\n\n            <button type=\"submit\">Link</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n    private Card? _linkingCard;\n\n    private LinkCardsModel _linkCardsModel = new();\n\n    private string? _cardError;\n\n    private EditContext _editContext = new(new LinkCardsModel());\n\n    public void Open(string elementId, Card card, Card linkingCard) \n    {\n        _card = card;\n        _linkingCard = linkingCard;\n        _cardError = null;\n        _linkCardsModel = new();\n        _editContext = new EditContext(_linkCardsModel);\n        StateHasChanged();\n        _modalRef?.Open(elementId);\n    }\n\n    public async Task OnSubmitAttempted() \n    {\n        if(_card is null || _linkingCard is null)\n            return;\n\n        _cardError = null;\n\n        if (!_editContext.Validate())\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var card = await db.Cards\n            .Include(x => x.LinkedIssuesOne)\n            .Include(x => x.LinkedIssuesTwo)\n            .Include(x => x.Activities)\n            .Include(x => x.Column)\n                .ThenInclude(x => x.Board)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var targetCard = await db.Cards\n            .Include(x => x.LinkedIssuesOne)\n            .Include(x => x.LinkedIssuesTwo)\n            .Include(x => x.Activities)\n            .Include(x => x.Column)\n                .ThenInclude(x => x.Board)\n            .FirstOrDefaultAsync(x => x.Id == _linkingCard.Id);\n\n        if (targetCard is null) \n        {\n            _cardError = \"Target card does not exist anymore.\";\n            return;\n        }\n\n        if(targetCard.Id.Equals(card.Id))\n        {\n            _cardError = \"You cannot link this card to itself.\";\n            return;\n        }\n\n        if(card.LinkedIssuesOne.Any(x => x.CardTwoId.Equals(targetCard.Id)))\n        {\n            _cardError = \"This card is already linked to the target card.\";\n            return;\n        }\n\n        card.LinkedIssuesOne.Add(new CardLink\n        {\n            CardOneId = card.Id,\n            CardTwoId = targetCard.Id,\n            Category = _linkCardsModel.Text\n        });\n\n        var oppositeCategory = Constants.LINK_TYPE_PAIRS.ContainsKey(_linkCardsModel.Text) ? Constants.LINK_TYPE_PAIRS[_linkCardsModel.Text] : Constants.LINK_TYPE_PAIRS.First(x => x.Value.Equals(_linkCardsModel.Text)).Key;\n\n        targetCard.LinkedIssuesOne.Add(new CardLink\n            {\n                CardOneId = targetCard.Id,\n                CardTwoId = card.Id,\n                Category = oppositeCategory\n            });\n\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>added</b> a linked issue <b>{targetCard.Column.Board.Code}-{targetCard.Number}</b> with <b>{_linkCardsModel.Text}</b> relationship\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n        targetCard.Activities.Add(new Activity\n            {\n                Text = $\"<b>added</b> a linked issue <b>{card.Column.Board.Code}-{card.Number}</b> with <b>{oppositeCategory}</b> relationship\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/PriorityModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Priority\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <div class=\"flex w-36 flex-col gap-1\">\n            <div class=\"priority-selector-item\" @onclick=\"() => OnChangeTo(CardPriority.Normal)\">\n                <PriorityLabel Priority=\"CardPriority.Normal\"/>\n\n                @if(_card.Priority.Equals(CardPriority.Normal)) {\n                    <i class=\"fa fa-check text-icon\" title=\"Selected\"></i>\n                }\n            </div>\n            <div class=\"priority-selector-item\" @onclick=\"() => OnChangeTo(CardPriority.Medium)\">\n                <PriorityLabel Priority=\"CardPriority.Medium\"/>\n\n                @if(_card.Priority.Equals(CardPriority.Medium)) {\n                    <i class=\"fa fa-check text-icon\" title=\"Selected\"></i>\n                }\n            </div>\n            <div class=\"priority-selector-item\" @onclick=\"() => OnChangeTo(CardPriority.High)\">\n                <PriorityLabel Priority=\"CardPriority.High\"/>\n\n                @if(_card.Priority.Equals(CardPriority.High)) {\n                    <i class=\"fa fa-check text-icon\" title=\"Selected\"></i>\n                }\n            </div>\n            <div class=\"priority-selector-item\" @onclick=\"() => OnChangeTo(CardPriority.Critical)\">\n                <PriorityLabel Priority=\"CardPriority.Critical\"/>\n\n                @if(_card.Priority.Equals(CardPriority.Critical)) {\n                    <i class=\"fa fa-check text-icon\" title=\"Selected\"></i>\n                }\n            </div>\n        </div>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard {get; set;}\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    public void Open(ElementReference? triggerElement, Card card) {\n        _card = card;\n        _modalRef?.Open(triggerElement);\n    }\n\n    public async Task OnChangeTo(CardPriority priority) {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null || card.Priority.Equals(priority))\n            return;\n\n        card.Priority = priority;\n        card.Activities.Add(new Activity\n            {\n                Text = $\"<b>changed</b> the priority to <b>{priority}</b>\",\n                UserId = _user.Id,\n                CardId = card.Id,\n            });\n        await db.SaveChangesAsync();\n\n        _card = card;\n        await UpdateCard.InvokeAsync();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/SearchModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject NavigationManager _navigationManager\n@inherits AbstractModal\n@implements IDisposable\n@inject IJSRuntime _js\n@inject SearchService _searchService\n\n<Modal Class=\"text-app-text\" @ref=\"Modal\" Title=\"Search\" DisableButtons=true ForceOverlay=true OnShown=\"OnShown\">\n    <input @ref=_input class=\"w-80 rounded-2xl bg-search-bar p-2 text-center text-xs\" autofocus type=\"search\"\n           placeholder=\"Search for tasks ...\" @oninput=\"UpdateSearchTerm\"/>\n\n    @if(_isLoading)\n    {\n        <Spinner/>\n    } else {\n        foreach(var card in _resultCards)\n        {\n            <div class=\"flex cursor-pointer flex-col justify-between px-3 py-2 text-xs hover:bg-dropdown-option\" @onclick='async () => await OnSelectedCard(card)'>\n                <div class=\"flex flex-row justify-between gap-3\">\n                    <label class=\"cursor-pointer whitespace-nowrap\">@card.Column.Board.Code-@card.Number</label>\n                    <label class=\"cursor-pointer truncate whitespace-nowrap\">@card.Name</label>\n                </div>\n                <label class=\"text-2xs cursor-pointer font-light\">Project @card.Column.Board.Project.Name – @card.Column.Board.Name</label>\n            </div>\n        }\n    }\n</Modal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public LinkCardsModal? LinkCardsModal { get; set; }\n\n    [Parameter]\n    public Card? CardToLink { get; set; }\n\n    private Timer? _timer;\n    private string? _searchTerm;\n    private bool _isLoading;\n    private ElementReference? _input;\n\n    private List<Card> _resultCards = [];\n\n    protected override void OnAfterRender(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        StateHasChanged();\n\n        _timer = new Timer(2000);\n        _timer.Stop();\n        _timer.Elapsed += Filter;\n        _timer.AutoReset = false;\n    }\n\n    private async Task OnShown()\n    {\n        if (_input.HasValue)\n            await _input.Value.FocusAsync();\n    }\n\n    private void UpdateSearchTerm(ChangeEventArgs e)\n    {\n        _searchTerm = e.Value as string;\n\n        _timer?.Stop();\n        _timer?.Start();\n\n        _isLoading = true;\n        StateHasChanged();\n    }\n\n    private async Task OnSelectedCard(Card card)\n    {\n        if (LinkCardsModal is null || CardToLink is null) \n        {\n            await GoToCard(card.Column.BoardId, card.Id);\n            return;\n        }\n\n        await Modal!.Close();\n        await _js.InvokeVoidAsync(\"closeDropdowns\");\n        LinkCardsModal.Open(\"linked_cards\", CardToLink, card);\n    }\n\n    private async Task GoToCard(int boardId, int cardId)\n    {\n        await Modal!.Close();\n        _navigationManager.NavigateTo($\"/boards/{boardId}/{cardId}\");\n        await _js.InvokeVoidAsync(\"closeDropdowns\");\n    }\n\n    private async void Filter(Object? obj = null, ElapsedEventArgs? e = null)\n    {\n        _resultCards = await _searchService.SearchAsync(_searchTerm, _user);\n        _isLoading = false;\n        await InvokeAsync(StateHasChanged);\n    }\n\n    void IDisposable.Dispose()\n        => _timer?.Dispose();\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/SnoozeCardModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"Snooze card\">\n    @if(_card is null) {\n        <Spinner/>\n    } else {\n        <EditForm class=\"form p-2\" Model=\"_snoozeCardModel\" OnValidSubmit=\"SnoozeCard\">\n            <DataAnnotationsValidator />\n\n            <div class=\"form-group\">\n                <Name For=\"() => _snoozeCardModel.At\" />\n                <InputDate class=\"form-control\" @bind-Value=\"_snoozeCardModel.At\" min=\"@DateTime.Today.ToHtmlDateString()\" />\n                <ValidationMessage For=\"() => _snoozeCardModel.At\" />\n            </div>\n            <div class=\"form-group\">\n                <Name For=\"() => _snoozeCardModel.Time\" />\n                <TimeSelect @bind-Value=\"_snoozeCardModel.Time\" />\n                <ValidationMessage For=\"() => _snoozeCardModel.Time\" />\n            </div>\n\n            <button type=\"submit\">Set</button>\n        </EditForm>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    private ActionModal? _modalRef;\n\n    private Card? _card;\n\n    private SnoozeCardModel _snoozeCardModel = new();\n\n    public void Open(ElementReference? triggerElement, Card card) {\n        _card = card;\n        _snoozeCardModel = new()\n            {\n                At = card.SnoozedUntil ?? DateTime.Today,\n                Time = (card.SnoozedUntil ?? DateTime.Now.AddHours(1).AddMinutes(-DateTime.Now.Minute)).ToString(\"HH:mm\")\n            };\n        _modalRef?.Open(triggerElement);\n        StateHasChanged();\n    }\n\n    public async Task SnoozeCard() \n    {\n        if(_card is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var card = await db.Cards\n            .Include(x => x.Activities)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_card.Id));\n\n        if(card is null)\n            return;\n\n        var time = DateTime.ParseExact(_snoozeCardModel.Time, \"HH:mm\", null);\n\n        card.SnoozedUntil = new DateTime(_snoozeCardModel.At.Year, _snoozeCardModel.At.Month, _snoozeCardModel.At.Day, time.Hour, time.Minute, 0);\n        card.Activities.Add(new Activity\n        {\n            Text = $\"<b>snoozed</b> this card until <b>{card.SnoozedUntil.Value.ToReadableStringWithTime()}</b>\",\n            UserId = _user.Id,\n            CardId = card.Id,\n        });\n\n        await db.SaveChangesAsync();\n\n        _card = card;\n        StateHasChanged();\n        await UpdateCard.InvokeAsync();\n        _modalRef?.Close();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Dialogs/UserInfoModal.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<ActionModal @ref=_modalRef Title=\"User information\">\n    @if(_targetUser is null) {\n        <Spinner/>\n    } else\n    {\n        <div class=\"flex flex-col items-center gap-2 p-2\">\n            <div class=\"avatar !h-10 !w-10\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_targetUser.ProfilePictureFileName');\"></div>\n            <label class=\"font-bold\">@_targetUser.DisplayName</label>\n            <div class=\"flex flex-col items-center gap-1\">\n                @foreach(var commonProjectMembership in _targetUser.ProjectMemberships.Where(x => _user.ProjectMemberships.Any(userMembership => userMembership.ProjectId.Equals(x.ProjectId))))\n                {\n                    <label class=\"text-sm\"><i class=\"fa fa-building icon\" title=\"Project membership\"></i>@(commonProjectMembership.IsAdmin ? \"Admin\" : \"Member\") of project @commonProjectMembership.Project.Name</label>\n                }\n                @foreach (var commonBoardMembership in _targetUser.BoardMemberships.Where(x => _user.BoardMemberships.Any(userMembership => userMembership.BoardId.Equals(x.BoardId)) || _user.ProjectMemberships.Any(userMembership => userMembership.ProjectId.Equals(x.Board.ProjectId))))\n                {\n                    <label class=\"text-sm\"><i class=\"fa fa-building icon\" title=\"Board membership\"></i>@(commonBoardMembership.IsAdmin ? \"Admin\" : \"Member\") of board @commonBoardMembership.Board.Name</label>\n                }\n            </div>\n        </div>\n    }\n</ActionModal>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    private ActionModal? _modalRef;\n\n    private User? _targetUser;\n\n    public async void Open(string elementId, int? targetUserId)\n    {\n        if(!targetUserId.HasValue)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _targetUser = await db.Users\n            .AsNoTracking()\n            .Include(x => x.ProjectMemberships)\n                .ThenInclude(x => x.Project)\n            .Include(x => x.BoardMemberships)\n                .ThenInclude(x => x.Board)\n            .FirstOrDefaultAsync(x => x.Id.Equals(targetUserId.Value));\n\n        if(_targetUser is null)\n            return;\n\n        StateHasChanged();\n        _modalRef?.Open(elementId);\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/ActionModal.razor",
    "content": "﻿@inject IJSRuntime _js\n\n<div @ref=\"_element\" class=\"dropdown dropdown-animate absolute top-0 left-0 z-20 hidden overflow-y-auto rounded-xs bg-modal shadow-2xl\">\n\t<section class=\"flex w-full flex-row items-center justify-center gap-10 px-2 py-3\">\n\t\t<label class=\"text-sm font-normal\">@Title</label>\n\t\t<i class=\"fa fa-xmark card-button ml-auto\" @onclick=\"Close\" title=\"Close\"></i>\n\t</section>\n\t<hr/>\n\t<div class=\"px-2 py-2\">\n\t\t@ChildContent\n\t</div>\n</div>\n\n@code {\n\t[Parameter]\n\tpublic required RenderFragment ChildContent { get; set; }\n\n\t[Parameter]\n\tpublic required string Title { get; set; }\n\n\tprivate ElementReference? _element;\n\tprivate string? _elementId;\n\tprivate ElementReference? _triggerElement;\n\n\tpublic async void Open(string elementId)\n\t{\n\t\t_elementId = elementId;\n\t\tawait OnResized();\n\t\tawait TrapFocus();\n\t}\n\n\tpublic async void Open(ElementReference? triggerElement)\n\t{\n\t\t_triggerElement = triggerElement;\n\t\tawait OnResized();\n\t\tawait TrapFocus();\n\t}\n\n\tpublic async Task TrapFocus()\n\t{\n\t\tif(!_element.HasValue)\n\t\t\treturn;\n\n\t\tawait Task.Delay(100);\n\t\tawait _js.InvokeVoidAsync(\"trapFocusInElement\", _element.Value);\n\t}\n\n\tpublic async Task OnResized()\n\t{\n\t\tif(_triggerElement is not null)\n\t\t\tawait _js.InvokeVoidAsync(\"openDropDownOnElementPosition\", _element, _triggerElement);\n\n\t\tif (_elementId is not null)\n\t\t\tawait _js.InvokeVoidAsync(\"openDropDownOnElementId\", _element, _elementId);\n\t}\n\n\tpublic async void Close() \n\t{\n\t\tawait _js.InvokeVoidAsync(\"closeDropdowns\");\n\t}\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/BoardCard.razor",
    "content": "@inject NavigationManager _navigationManager\n@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<EditBoardModal @ref=\"_editBoardModal\" OnSubmit=\"OnEdit\" />\n<CloneBoardModal @ref=\"_cloneBoardModal\" OnCloned=\"OnEdit\" />\n\n<div class=\"board-card\" @onclick='GoToBoard'>\n    <div class=\"flex w-full flex-row justify-end gap-2 align-middle\">\n        <i class='@(Board.Favorites.Any(x => x.UserId.Equals(_user.Id)) ? \"fa-solid\" : \"fa-regular\") fa-star card-button' @onclick='MakeFavorite' @onclick:stopPropagation=\"true\" title=\"@(Board.Favorites.Any(x => x.UserId.Equals(_user.Id)) ? \"Remove from favorites\" : \"Add to favorites\")\"></i>\n        @if (IsAdmin)\n        {\n            <Dropdown Actions='new() {\n                        { \"Edit board\", () => _editBoardModal?.Open(Board.Id) },\n                        { \"Clone board\", () => _cloneBoardModal?.Open(Board) },\n                        { \"Delete board\", async () => await DeleteConfirmationDialog.OpenDialog(Board) }\n                    }'>\n                <i class=\"fa fa-ellipsis card-button\" title=\"Board options\"></i>\n            </Dropdown>\n        }\n    </div>\n\n        <div class=\"flex flex-col gap-2\">\n            <label class=\"cursor-pointer text-xl font-semibold text-card-heading\">@Board.Name</label>\n            <label class=\"text-card-data-points cursor-pointer text-xs\">@Board.Description</label>\n        </div>\n\n        <div class=\"mt-5 flex flex-row items-center justify-between\">\n            <div class=\"flex flex-col gap-2\">\n            @{\n                var lastVisit = Board.LastVisits.FirstOrDefault(x => x.UserId.Equals(_user.Id));\n                var trackedTime = new TimeSpan(Board.Columns.SelectMany(x => x.Cards).SelectMany(x => x.TimeRecords).Select(x => ((x.EndedAt ?? DateTime.Now) - x.StartedAt).Ticks).Sum()).ToElapsedString(true);\n            }\n            <label class=\"board-card-data-point\"><i class=\"fa-regular fa-calendar\" title=\"Last visited\"></i> @(lastVisit is null ? \"never\" : lastVisit.VisitTime.ToElapsedString())</label>\n            @if (!string.IsNullOrWhiteSpace(trackedTime))\n            {\n                <label class=\"board-card-data-point\"><i class=\"fa-regular fa-hourglass\" title=\"Total time tracked\"></i> @trackedTime</label>\n            }\n        </div>\n            <div class=\"flex flex-row gap-1\">\n                @foreach(var member in _members) \n                {\n                    <div class=\"avatar stack-avatars\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@member.ProfilePictureFileName');\"></div>\n                }\n            </div>\n        </div>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public EventCallback OnEdit { get; set; }\n\n    [Parameter]\n    public required DeleteConfirmationDialog<Board> DeleteConfirmationDialog { get; set; }\n\n    [Parameter]\n    public EventCallback<bool> OnFavorite { get; set; }\n\n    [Parameter]\n    public required Board Board { get; set; }\n\n    private List<User> _members\n    {\n        get => (Board.Memberships.Select(x => x.User).Concat(Board.Project?.Memberships?.Select(x => x.User) ?? [])).DistinctBy(x => x.Id).ToList();\n    }\n\n    [Parameter]\n    public bool IsAdmin { get; set; }\n\n    private EditBoardModal? _editBoardModal;\n    private CloneBoardModal? _cloneBoardModal;\n\n    private void GoToBoard() {\n        _navigationManager.NavigateTo(_navigationManager.BaseUri + \"boards/\" + Board.Id);\n    }\n\n    private async Task MakeFavorite(MouseEventArgs e)\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .Include(x => x.Favorites)\n            .FirstOrDefaultAsync(x => x.Id.Equals(Board.Id));\n\n        if (board is null)\n            return;\n\n        var existingFavorite = board.Favorites.FirstOrDefault(x => x.UserId.Equals(_user.Id));\n\n        bool newState = false;\n\n        if (existingFavorite is null)\n        {\n            board.Favorites.Add(new()\n            {\n                UserId = _user.Id,\n                BoardId = board.Id\n            });\n            newState = true;\n        }\n        else\n            board.Favorites.Remove(existingFavorite);\n\n        await db.SaveChangesAsync();\n        await OnFavorite.InvokeAsync(newState);\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/CardView.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n\n<div id=\"@Card.Id\" data-blocked=\"@Card.Flagged.ToString()\" class=\"task-card\" @onclick=\"() => EditCardModal.Open(Card.Id, Members, Columns)\">\n    <div class=\"flex flex-row items-center justify-between gap-2\">\n        <div class=\"flex flex-row flex-wrap items-center justify-start gap-1\">\n            <PriorityLabel Priority=\"Card.Priority\"/>\n            @foreach(var label in Card.Labels) {\n                <LabelView Label=\"label\"></LabelView>\n            }\n        </div>\n\n        <Dropdown Actions='new() {\n                                { \"Edit task\", async () => await EditCardModal.Open(Card.Id, Members, Columns) },\n                                { \"Delete task\", () => DeleteCardModal?.OpenDialog(Card) },\n                                { $\"{(Card.Flagged ? \"Unmark\" : \"Mark\")} as flagged\", async () => await ChangeFlaggedStatus() }\n                            }'>\n            <i class=\"fa fa-ellipsis card-button pr-1\" title=\"Card options\"></i>\n        </Dropdown>\n    </div>\n    <label class=\"cursor-pointer text-xs break-normal break-words\">\n        @Card.Name\n    </label>\n    <div class=\"flex flex-row items-center justify-between gap-3\">\n        <div class=\"text-card-data-points flex w-full flex-row flex-wrap items-center justify-start gap-x-3 gap-y-1 text-xs\">\n            @if (Card.Deadline is not null)\n            {\n                DeadlineColor color = Column.Finished ? DeadlineColor.Green : (DateTime.Compare(Card.Deadline.Value, DateTime.Now) < 0 ? DeadlineColor.Red : (Card.Deadline.Value.Date == DateTime.Today.Date ? DeadlineColor.Yellow : DeadlineColor.Default));\n                <label data-coloring=\"@color\" class=\"card-data-point rounded-lg px-1 py-1 text-white capitalize data-[coloring=Default]:text-card-data-points data-[coloring=Default]:mx-[-0.25rem] data-[coloring=Green]:bg-green-500 data-[coloring=Yellow]:bg-yellow-500 data-[coloring=Red]:bg-red-500\"><i class=\"fa fa-clock\" title=\"Deadline\"></i> @Card.Deadline.Value.ToShortString()</label>\n            }\n            <label class=\"card-data-point\"><i class=\"fa fa-hashtag\" title=\"Card ID\"></i> @(BoardCode)-@Card.Number</label>\n            @if (Card.Attachments.Any())\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-paperclip\" title=\"Attachments\"></i> @Card.Attachments.Count</label>\n            }\n            @if (Card.Subtasks.Any())\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-check\" title=\"Subtasks\"></i> @Card.Subtasks.Count(x => x.Completed)/@Card.Subtasks.Count</label>\n            }\n            @{\n                var trackedTime = Card.GetTotalTime().ToElapsedString(true);\n            }\n            @if (!string.IsNullOrWhiteSpace(trackedTime))\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-stopwatch\" title=\"Time tracked\"></i> @trackedTime</label>\n            }\n            @if(Card.Flagged)\n            {\n                <label class=\"card-data-point text-card-blocked-text\"><i class=\"fa fa-flag\" title=\"Flagged\"></i> Flagged</label>\n            }\n            @if (Card.SnoozedUntil is not null)\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-moon\" title=\"Snoozed until\"></i> @(Card.SnoozedUntil.Value.ToShortString())</label>\n            }\n            @if (!string.IsNullOrWhiteSpace(Card.Description))\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-align-left\" title=\"Has description\"></i></label>\n            }\n            @if(Card.RepeatInfo is not null)\n            {\n                <label class=\"card-data-point\"><i class=\"fa fa-repeat\" title=\"Repeating task\"></i> @(LongFormRepeat ? $\"{Card.RepeatInfo.GetRepeatString()}, next repeat {_nextRepeat}\" : string.Empty)</label>\n            }\n        </div>\n        <div class=\"flex\">\n            @foreach(var assignee in Card.Assignees) \n            {\n                <div class=\"avatar stack-avatars !ml-[-0.8rem] !h-6 !w-6\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@assignee.ProfilePictureFileName');\"></div>\n            }\n        </div>\n    </div>\n</div>\n\n@code {\n    [Parameter]\n    public required EditCardModal EditCardModal {get; set;}\n\n    [Parameter]\n    public required DeleteConfirmationDialog<Card> DeleteCardModal { get; set; }\n\n    [Parameter]\n    public required Card Card { get; set; }\n\n    [Parameter]\n    public required Column Column { get; set; }\n\n    [Parameter]\n    public required string BoardCode { get; set; }\n\n    [Parameter]\n    public required List<User> Members { get; set; }\n\n    [Parameter]\n    public required List<Column> Columns { get; set; }\n\n    [Parameter]\n    public bool LongFormRepeat { get; set; }\n\n    [Parameter]\n    public EventCallback OnCardUpdated { get; set; }\n\n    private string? _nextRepeat;\n\n    protected override void OnParametersSet()\n    {\n        base.OnParametersSet();\n\n        if(Card.RepeatInfo is not null)\n            _nextRepeat = Card.CalculateNextRepeat(DateTime.Now).ToReadableStringWithTime();\n    }\n\n    private async Task ChangeFlaggedStatus()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var card = await db.Cards.FindAsync(Card.Id);\n\n        if (card is null)\n            return;\n\n        card.Flagged = !card.Flagged;\n        Card.Flagged = card.Flagged;\n\n        await db.SaveChangesAsync();\n        StateHasChanged();\n        await OnCardUpdated.InvokeAsync();\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/ColumnView.razor",
    "content": "@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject IJSRuntime _js\n@inject CardNumberingService _cardNumberingService\n@inject ILogger<ColumnView> _logger\n@inherits NotifiableBase\n\n@{\n    var columnCards = Cards.Where(x => x.ColumnId.Equals(Column.Id)).ToList();\n    var cardsCount = columnCards.Count;\n}\n<div @key=\"Column.Id\" id=\"@Column.Id\" class=\"board-column max-h-visible-screen gap-1\">\n    <div class=\"flex w-full flex-row items-start justify-between\">\n        <div class=\"flex flex-row items-center gap-2\">\n            <label class=\"align-middle\">\n                @Column.Name\n                <span class='text-2xs ml-1 rounded-full p-0.5 align-middle shadow-sm @(Column.MaxCards != 0 && cardsCount >= Column.MaxCards ? \"bg-column-limit-reached\" : \"bg-card-bg\")'>\n                    @if (Column.MaxCards == 0)\n                    {\n                        <span>@cardsCount</span>\n                    }\n                    else\n                    {\n                        <span>@cardsCount/@Column.MaxCards</span>\n                    }\n                </span>\n                @if (Column.Collapsed)\n                {\n                    <label class=\"ml-2 text-xs font-normal\">(Collapsed)</label>\n                }\n            </label>\n        </div>\n\n        @if (IsAdmin())\n        {\n            <div class=\"flex flex-row items-center gap-2\">\n                <i class=\"fa fa-up-down-left-right drag-toggle icon-button cursor-move text-icon\" title=\"Drag to reorder column\"></i>\n\n                <Dropdown Actions='new() {\n                    { \"Edit column\", () => EditColumnModal?.Open(Column.Id) },\n                    { \"Delete column\", async () => await OpenDeleteColumnDialog(Column) },\n                    { $\"{(Column.Collapsed ? \"Expand\" : \"Collapse\")} column\", async () => await ExpandOrCollapseColumn(Column.Id) },\n                }'>\n                <i class=\"fa fa-ellipsis icon-button pr-1\" title=\"Column options\"></i>\n                </Dropdown>\n            </div>\n        }\n    </div>\n\n    @if (!Column.Collapsed)\n    {\n        <SortableList Id=@($\"{COLUMN_PREFIX}{Column.Id}\") Animation=@(Board.DisableSortingAnimations ? 0 : 200) Class=\"min-h-[1rem] w-full overflow-y-auto\" Group=\"group\" Items=\"columnCards.OrderBy(x => x.Index).ToList()\" MaxItems=Column.MaxCards Context=\"context\" OnRemove=\"OnMovedFromColumn\" OnUpdate=\"OnMovedWithinList\" OnExceededLimit=\"OnExceededCardLimit\">\n            <SortableItemTemplate>\n                <CardView @key=\"context.Id\" Card=\"@context\" Column=\"Column\" BoardCode=\"@Board.Code\" EditCardModal=\"EditCardModal\" DeleteCardModal=\"DeleteCardModal\" Members=\"Members\" OnCardUpdated=\"OnUpdate\" Columns=\"Board.Columns\" />\n            </SortableItemTemplate>\n        </SortableList>\n\n        @if (Column.MaxCards == 0 || cardsCount < Column.MaxCards)\n        {\n            <div data-active=@(AddingCardHere.ToString()) @onclick=\"() => StartAddingToColumn(Column.Id)\"\n                 class=\"add rounded-lg select-none p-5 h-min w-full to-task-card\">\n                @if (!AddingCardHere)\n                {\n                    <i class=\"fa fa-plus text-3xl\" title=\"Add new card\"></i>\n                    <label>New card</label>\n                }\n                else\n                {\n                    <div class=\"flex w-full flex-row items-center justify-between text-sm font-semibold\">\n                        <label>Create new card</label>\n                        <i class=\"fa fa-xmark card-button\" @onclick=\"() => AddingSetter.InvokeAsync(-1)\" @onclick:stopPropagation=true title=\"Cancel\"></i>\n                    </div>\n\n                    <textarea class=\"h-16 w-full rounded-lg bg-card-bg p-2 text-start text-xs outline-1 outline-typing-outline\"\n                              @bind=\"CreateTaskText\"\n                              @bind:event=\"oninput\"\n                              @ref=_textElement\n                              @onkeydown='async (e) => {\n                              if (!e.Key.Contains(\"Enter\"))\n                                  return;\n\n                              await AttemptCreateTaskSubmit(Column.Id);\n                          }'\n                            autofocus placeholder=\"Describe the task ...\" wrap=\"soft\" />\n\n                <hr class=\"border-t-tab-outline\">\n                <button class=\"w-full\" @onclick=\"async () => await AttemptCreateTaskSubmit(Column.Id)\" @onclick:stopPropagation=\"true\">Create</button>\n            }\n        </div>\n    }\n        }\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User User { get; set; } = default!;\n\n    [Parameter]\n    public required Column Column { get; set; }\n\n    [Parameter]\n    public required Board Board { get; set; }\n\n    [Parameter]\n    public required List<User> Members { get; set; }\n\n    [Parameter]\n    public required List<Card> Cards { get; set; }\n\n    [Parameter]\n    public required EditCardModal EditCardModal { get; set; }\n\n    [Parameter]\n    public required EditColumnModal EditColumnModal { get; set; }\n\n    [Parameter]\n    public required DeleteConfirmationDialog<Column> DeleteColumnModal { get; set; }\n\n    [Parameter]\n    public required DeleteConfirmationDialog<Card> DeleteCardModal { get; set; }\n\n    [Parameter]\n    public required Func<bool> IsAdmin { get; set; }\n\n    [Parameter]\n    public required bool AddingCardHere { get; set; }\n\n    [Parameter]\n    public required EventCallback<int> AddingSetter { get; set; }\n\n    [Parameter]\n    public required EventCallback OnCardMoved { get; set; }\n\n    [Parameter]\n    public required EventCallback OnUpdate { get; set; }\n\n    private const string COLUMN_PREFIX = \"column_\";\n    private ElementReference? _textElement;\n    private CreateCardModel _createTaskModel = new();\n\n    private int GetColumnIdFromString(string str)\n        => Convert.ToInt32(str.Replace(COLUMN_PREFIX, string.Empty));\n\n    private async Task OnMovedWithinList((string movedCardId, string? targetCardId, string columnId) args)\n    {\n        var columnId = GetColumnIdFromString(args.columnId);\n        var movedCardId = Convert.ToInt32(args.movedCardId);\n\n        var snapshot = Cards.Select(c => new { c.Id, c.ColumnId, c.Index }).ToList();\n\n        var targetColumnCards = Cards.Where(c => c.ColumnId == columnId).OrderBy(c => c.Index).ToList();\n        var movedCard = targetColumnCards.FirstOrDefault(x => x.Id == movedCardId);\n\n        if (movedCard is null)\n            return;\n\n        int targetIndex = targetColumnCards.Any() ? targetColumnCards.Max(x => x.Index) + 1 : 0;\n        int? targetCardId = args.targetCardId is not null ? Convert.ToInt32(args.targetCardId) : null;\n\n        if (targetCardId is not null)\n        {\n            var targetCard = targetColumnCards.FirstOrDefault(x => x.Id.Equals(targetCardId));\n            if (targetCard is not null)\n            {\n                targetIndex = targetCard.Index;\n                foreach (var card in targetColumnCards.OrderByDescending(x => x.Index))\n                {\n                    if (card.Index >= targetCard.Index)\n                        card.Index++;\n                }\n            }\n        }\n\n        movedCard.Index = targetIndex;\n        IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == columnId).ToList());\n\n        StateHasChanged();\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var dbTargetColumn = db.Columns\n                .Include(x => x.Cards)\n                .First(x => x.Id.Equals(columnId));\n\n            var dbMovedCard = dbTargetColumn.Cards.OrderBy(x => x.Index).First(x => x.Id.Equals(movedCardId));\n\n            int dbTargetIndex = dbTargetColumn.Cards.Any() ? dbTargetColumn.Cards.Max(x => x.Index) + 1 : 0;\n\n            if (targetCardId is not null)\n            {\n                var dbTargetCard = dbTargetColumn.Cards.FirstOrDefault(x => x.Id.Equals(targetCardId));\n                if (dbTargetCard is not null)\n                {\n                    dbTargetIndex = dbTargetCard.Index;\n                    foreach (var card in dbTargetColumn.Cards.OrderByDescending(x => x.Index))\n                    {\n                        if (card.Index >= dbTargetCard.Index)\n                            card.Index++;\n                    }\n                }\n            }\n\n            dbMovedCard.Index = dbTargetIndex;\n            IndexHelper.FixIndices(dbTargetColumn.Cards);\n\n            await db.SaveChangesAsync();\n            await OnUpdate.InvokeAsync();\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(ex, \"Failed to persist moved card within column.\");\n            foreach (var oldCardPosition in snapshot)\n            {\n                var card = Cards.FirstOrDefault(x => x.Id == oldCardPosition.Id);\n\n                if (card is not null)\n                {\n                    card.ColumnId = oldCardPosition.ColumnId;\n                    card.Index = oldCardPosition.Index;\n                }\n            }\n\n            IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == columnId).ToList());\n            StateHasChanged();\n\n            MainLayout.RunNotification(new(\"Failed to move card. Changes were reverted.\", NotificationType.Fail));\n        }\n    }\n\n    private void OnExceededCardLimit()\n        => MainLayout.RunNotification(new(\"The card could not be moved to this column due to it being already full.\", NotificationType.Fail));\n\n    private async Task OnMovedFromColumn((string movedCardId, string? targetCardId, string oldColumnId, string newColumnId, double x, double y) args)\n    {\n        if (Board is null)\n            return;\n\n        var oldColumnId = GetColumnIdFromString(args.oldColumnId);\n        var newColumnId = GetColumnIdFromString(args.newColumnId);\n\n        var snapshot = Cards.Select(c => new { c.Id, c.ColumnId, c.Index }).ToList();\n\n        var movedCardId = Convert.ToInt32(args.movedCardId);\n        var oldColumnCards = Cards.Where(c => c.ColumnId == oldColumnId).OrderBy(c => c.Index).ToList();\n        var newColumnCards = Cards.Where(c => c.ColumnId == newColumnId).OrderBy(c => c.Index).ToList();\n\n        var movedCard = oldColumnCards.FirstOrDefault(x => x.Id == movedCardId);\n\n        if (movedCard is null)\n            return;\n\n        var newColumn = Board.Columns.First(c => c.Id == newColumnId);\n\n        if (newColumn.MaxCards != 0 && newColumnCards.Count + 1 > newColumn.MaxCards)\n        {\n            OnExceededCardLimit();\n            return;\n        }\n\n        oldColumnCards.Remove(movedCard);\n        IndexHelper.FixIndices(oldColumnCards);\n\n        int targetIndex = newColumnCards.Any() ? newColumnCards.Max(x => x.Index) + 1 : 0;\n        int? targetCardId = args.targetCardId is not null ? Convert.ToInt32(args.targetCardId) : null;\n\n        if (targetCardId is not null)\n        {\n            var targetCard = newColumnCards.FirstOrDefault(x => x.Id.Equals(targetCardId));\n\n            if (targetCard is not null)\n            {\n                targetIndex = targetCard.Index;\n\n                foreach (var card in newColumnCards.OrderByDescending(x => x.Index))\n                {\n                    if (card.Index >= targetCard.Index)\n                        card.Index++;\n                }\n            }\n        }\n\n        var masterMoved = Cards.First(x => x.Id == movedCardId);\n        masterMoved.ColumnId = newColumnId;\n        masterMoved.Column = newColumn;\n        masterMoved.Index = targetIndex;\n\n        IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == oldColumnId).ToList());\n        IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == newColumnId).ToList());\n\n        await OnCardMoved.InvokeAsync();\n\n        if (newColumn.Finished)\n            await _js.InvokeVoidAsync(\"triggerConfetti\", args.x, args.y);\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var targetColumns = await db.Columns\n                .Where(x => x.Id.Equals(oldColumnId) || x.Id.Equals(newColumnId))\n                .Include(x => x.Cards)\n                .ToListAsync();\n\n            var dbOldColumn = targetColumns.First(x => x.Id.Equals(oldColumnId));\n            var dbNewColumn = targetColumns.First(x => x.Id.Equals(newColumnId));\n\n            if (dbNewColumn.MaxCards != 0 && dbNewColumn.Cards.Count + 1 > dbNewColumn.MaxCards)\n            {\n                throw new IndexOutOfRangeException(\"Target column is full.\");\n            }\n\n            var dbMovedCard = dbOldColumn.Cards.OrderBy(x => x.Index).First(x => x.Id.Equals(movedCardId));\n            dbOldColumn.Cards.Remove(dbMovedCard);\n            IndexHelper.FixIndices(dbOldColumn.Cards);\n\n            int dbTargetIndex = dbNewColumn.Cards.Any() ? dbNewColumn.Cards.Max(x => x.Index) + 1 : 0;\n\n            if (targetCardId is not null)\n            {\n                var dbTargetCard = dbNewColumn.Cards.FirstOrDefault(x => x.Id.Equals(targetCardId));\n\n                if (dbTargetCard is not null)\n                {\n                    dbTargetIndex = dbTargetCard.Index;\n                    foreach (var card in dbNewColumn.Cards.OrderByDescending(x => x.Index))\n                    {\n                        if (card.Index >= dbTargetCard.Index)\n                            card.Index++;\n                    }\n                }\n            }\n\n            dbNewColumn.Cards.Add(dbMovedCard);\n            dbMovedCard.Index = dbTargetIndex;\n            dbMovedCard.ColumnId = newColumnId;\n\n            IndexHelper.FixIndices(dbNewColumn.Cards);\n\n            await db.SaveChangesAsync();\n            await OnUpdate.InvokeAsync();\n        }\n        catch (Exception ex)\n        {\n            foreach (var oldCardPosition in snapshot)\n            {\n                var card = Cards.FirstOrDefault(x => x.Id == oldCardPosition.Id);\n                if (card is not null)\n                {\n                    card.ColumnId = oldCardPosition.ColumnId;\n                    card.Index = oldCardPosition.Index;\n\n                    if (card.Id == movedCardId)\n                        card.Column = Board.Columns.First(c => c.Id.Equals(oldCardPosition.ColumnId));\n                }\n            }\n\n            IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == oldColumnId).ToList());\n            IndexHelper.FixIndices(Cards.Where(c => c.ColumnId == newColumnId).ToList());\n            await OnCardMoved.InvokeAsync();\n\n            if (ex is IndexOutOfRangeException)\n                OnExceededCardLimit();\n            else\n            {\n                _logger.LogError(ex, \"Failed to persist moved card from column.\");\n                MainLayout.RunNotification(new(\"Failed to move card. Changes were reverted.\", NotificationType.Fail));\n            }\n        }\n    }\n\n    private async Task ExpandOrCollapseColumn(int columnId)\n    {\n        ArgumentNullException.ThrowIfNull(Board);\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var targetColumn = Board.Columns.First(x => x.Id.Equals(columnId));\n        targetColumn.Collapsed = !targetColumn.Collapsed;\n        await db.Columns.Where(x => x.Id.Equals(columnId)).ExecuteUpdateAsync(x => x.SetProperty(y => y.Collapsed, targetColumn.Collapsed));\n\n        StateHasChanged();\n        await OnUpdate.InvokeAsync();\n    }\n\n    private async Task OpenDeleteColumnDialog(Column column)\n    {\n        ArgumentNullException.ThrowIfNull(DeleteColumnModal);\n\n        await DeleteColumnModal.OpenDialog(column, async () =>\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var targetBoard = await db.Boards\n                .Include(x => x.Columns)\n            .FirstOrDefaultAsync(x => x.Id.Equals(Column.BoardId));\n\n            if (targetBoard is null)\n                return;\n\n            targetBoard.Columns.FixIndices();\n\n            await db.SaveChangesAsync();\n        });\n    }\n\n    private void StartAddingToColumn(int columnId)\n    {\n        AddingSetter.InvokeAsync(columnId);\n\n        _ = FocusCardCreation();\n    }\n\n    private async Task FocusCardCreation()\n    {\n        await Task.Delay(10);\n\n        if (_textElement is null)\n            return;\n\n        await _textElement.Value.FocusAsync();\n    }\n\n    private async Task AttemptCreateTaskSubmit(int columnId)\n    {\n        if (_createTaskModel is null || string.IsNullOrWhiteSpace(_createTaskModel.Text))\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var column = await db.Columns\n            .Include(x => x.Cards)\n            .FirstOrDefaultAsync(x => x.Id.Equals(columnId));\n\n        if (column is null)\n            return;\n\n        int newIndex = 0;\n\n        switch (Column.NewCardPlacement)\n        {\n            case CardPlacement.Top:\n                {\n                    foreach (var card in column.Cards)\n                        card.Index++;\n                    break;\n                }\n            default:\n                newIndex = IndexHelper.GetNextIndex(column.Cards);\n                break;\n        }\n\n        var newCard = new Card\n        {\n            Name = _createTaskModel.Text,\n            ColumnId = columnId,\n            Index = newIndex,\n            CreatedAt = DateTime.Now,\n            Number = await _cardNumberingService.GetNextNumberAsync(Board.Id),\n            CreatedById = User.Id\n        };\n\n        if (User.AutomaticAssign)\n        {\n            var targetUser = await db.Users.FirstAsync(x => x.Id.Equals(User.Id));\n            newCard.Assignees.Add(targetUser);\n        }\n\n        column.Cards.Add(newCard);\n        await db.SaveChangesAsync();\n        await OnUpdate.InvokeAsync();\n\n        _createTaskModel = new();\n\n        await RunNotification(typeof(Card), OperationType.Added);\n\n        if (Board is not null && User.AutomaticCardEdit)\n            EditCardModal?.Open(newCard.Id, Members, Board.Columns);\n    }\n\n    private string CreateTaskText\n    {\n        get => _createTaskModel.Text ?? string.Empty;\n        set => _createTaskModel.Text = value?.ReplaceLineEndings(\" \") ?? string.Empty;\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/DisabledBadge.razor",
    "content": "<div class=\"label !cursor-help bg-gray-400 text-label-text\">\n    Disabled\n</div>"
  },
  {
    "path": "Ticky.Web/Components/Elements/Dropdown.razor",
    "content": "﻿@inject IJSRuntime _js\n\n<div @ref=\"_element\" @onclick=\"OpenMenu\" @onclick:stopPropagation=\"true\">\n\t@ChildContent\n</div>\n\n<div @ref=\"_dropdownElement\" class=\"dropdown fixed top-0 left-0 z-10 hidden rounded-xs bg-modal text-app-text shadow select-none dropdown-animate\">\n\t<div class=\"flex flex-col text-center text-sm\">\n\t\t@foreach(var action in Actions) \n\t\t{\n\t\t\t<div class='cursor-pointer @(action.Key.Contains(\"Delete\") || action.Key.Contains(\"Log out\") ? \"text-red-button\" : string.Empty) px-8 py-1 transition-all hover:bg-dropdown-option' \n\t\t\t\t@onclick=\"() => RunAction(action.Value)\" @onclick:stopPropagation=\"true\">@action.Key</div>\n\t\t}\n\t</div>\n</div>\n\n\n@code {\n\t[Parameter]\n\tpublic required RenderFragment ChildContent { get; set; }\n\n\t[Parameter]\n\tpublic required Dictionary<string, Action> Actions { get; set; }\n\n\t[Parameter]\n\tpublic bool Disabled { get; set; }\n\n\tprivate ElementReference? _element;\n\n\tprivate ElementReference? _dropdownElement;\n\n\tprivate async void OpenMenu(MouseEventArgs e)\n\t{\n\t\tif (Disabled)\n\t\t\treturn;\n\n\t\tawait _js.InvokeVoidAsync(\"onDropdownTriggerClicked\", e.ClientX, e.ClientY, _dropdownElement);\n\t}\n\n\tprivate async void RunAction(Action action)\n\t{\n\t\taction.Invoke();\n\t\tawait _js.InvokeVoidAsync(\"closeDropdowns\");\n\t}\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/LabelView.razor",
    "content": "<div class=\"label\" \n    style=\"background-color: rgba(@Label.BackgroundColor.R, @Label.BackgroundColor.G, @Label.BackgroundColor.B, @Label.BackgroundColor.A); color: rgba(@Label.TextColor.R, @Label.TextColor.G, @Label.TextColor.B, @Label.TextColor.A);\">\n    @Label.Name\n</div>\n\n@code {\n    [Parameter]\n    public required Label Label { get; set; }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/Modal.razor",
    "content": "@if(_triggeredShow)\n{\n\t<div data-active=\"@_shown.ToString()\" class='h-visible-screen fixed top-0 left-0 @(ForceOverlay ? \"z-50\" : \"z-10\") flex w-screen items-center justify-center bg-backdrop/0 transition-all ease-in-out data-[active=True]:bg-backdrop/40' @onmousedown=\"Cancel\" @onkeydown=\"this.OnKey\">\n\t\t<div role=\"dialog\" aria-modal=\"true\" data-active=\"@_shown.ToString()\" class='m-5 flex flex-col divide-y overflow-hidden rounded-lg bg-modal/0 transition-all ease-in-out data-[active=False]:translate-y-[500%] data-[active=True]:bg-modal/100 @(Large ? \"w-full max-w-full md:max-w-3xl\" : \"max-w-[1300px]\") @Class' @onmousedown:stopPropagation=true>\n\t\t\t@if(!DisableButtons || EnableTitle) \n\t\t\t{\n\t\t\t\t<section class=\"flex flex-row items-center justify-between gap-10 px-7 py-3\">\n\t\t\t\t\t<h5>@Title</h5>\n\t\t\t\t\t<i class=\"fa fa-xmark card-button\" @onclick=\"Cancel\" title=\"Close\"></i>\n\t\t\t\t</section>\n\t\t\t\t<section @ref=_childContent class=\"max-h-[80vh] overflow-y-auto px-7 py-5\">@ChildContent</section>\n\t\t\t\t@if (!DisableButtons)\n\t\t\t\t{\n\t\t\t\t\t<section class=\"flex flex-row justify-end gap-5 px-7 py-5\">\n\t\t\t\t\t\t<button class=\"!bg-cancel-button px-5 py-2 hover:!bg-cancel-button-hover\" @onclick=\"Cancel\">@CancelButtonText</button>\n\t\t\t\t\t\t<button class='px-5 py-2 @(RedSubmit ? \"!bg-red-button hover:!bg-red-button-hover\" : \"\")' @onclick=\"Submit\">@SubmitButtonText</button>\n\t\t\t\t\t</section>\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t@ChildContent\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n\n@code {\n\t[Parameter]\n\tpublic required string Title { get; set; }\n\n\t[Parameter]\n\tpublic string Class { get; set; } = string.Empty;\n\n\t[Parameter]\n\tpublic required RenderFragment ChildContent { get; set; }\n\n\t[Parameter]\n\tpublic EventCallback OnCancel { get; set; }\n\n\t[Parameter]\n\tpublic EventCallback OnSubmitAttempted { get; set; }\n\n\t[Parameter]\n\tpublic EventCallback OnClose { get; set; }\n\n\t[Parameter]\n\tpublic EventCallback OnShown { get; set; }\n\n\t[Parameter]\n\tpublic bool RedSubmit { get; set; }\n\n\t[Parameter]\n\tpublic bool DisableButtons { get; set; }\n\n\t[Parameter]\n\tpublic bool EnableTitle { get; set; }\n\n\t[Parameter]\n\tpublic bool Large { get; set; }\n\n\t[Parameter]\n\tpublic bool ForceOverlay { get; set; }\n\n\t[Parameter]\n\tpublic string CancelButtonText { get; set; } = \"Cancel\";\n\n\t[Parameter]\n    public string SubmitButtonText { get; set; } = \"Submit\";\n\n\tprivate bool _triggeredShow;\n\tprivate bool _shown;\n\tprivate ElementReference? _childContent;\n\n\tpublic async Task Show() \n\t{\n\t\tif(!_triggeredShow) \n\t\t{\n\t\t\t_triggeredShow = true;\n\t\t\tStateHasChanged();\n\t\t\tawait Task.Delay(5);\n\t\t}\n\t\t_shown = true;\n\t\tStateHasChanged();\n\t\tawait OnShown.InvokeAsync();\n\t}\n\n\tpublic async Task Close()\n\t{\n\t\t_shown = false;\n\t\tStateHasChanged();\n\t\tawait Task.Delay(200);\n\t\t_triggeredShow = false;\n\t\tStateHasChanged();\n\t}\n\n\tprivate async Task Cancel()\n\t{\n\t\tawait OnClose.InvokeAsync();\n\n\t\tawait OnCancel.InvokeAsync();\n\n\t\tawait Close();\n\t}\n\n\tprivate async Task Submit()\n\t{\n\t\tawait OnSubmitAttempted.InvokeAsync();\n\t}\n\n\tprivate async Task OnKey(KeyboardEventArgs e)\n\t{\n\t\tswitch(e.Key)\n\t\t{\n\t\t\tcase \"Enter\":\n\t\t\t{\n\t\t\t\tif(_childContent.HasValue)\n\t\t\t\t\tawait _childContent.Value.FocusAsync();\n\n\t\t\t\tawait OnSubmitAttempted.InvokeAsync();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"Escape\":\n\t\t\t\tawait Cancel();\n                break;\n\t\t}\n\t}\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/Notifications.razor",
    "content": "﻿<div class=\"fixed right-5 bottom-5 z-20 flex flex-col gap-10 transition-all\">\n    @foreach(var notification in _notifications) \n    {\n        <div class=\"flex flex-row content-between items-center gap-10 overflow-hidden rounded-md bg-modal shadow transition-all\">\n            <div class=\"flex flex-row content-start items-center gap-5\">\n                <div class='@(notification.Type == NotificationType.Success ? \"bg-green-500\" : \"bg-red-500\") h-16 w-2'>\n                </div>\n                <i class='@(notification.Type == NotificationType.Success ? \"text-green-500 fa-circle-check\" : \"text-red-500 fa-circle-xmark\") fa-regular text-2xl'></i>\n                <label class=\"text-sm\">\n                    @notification.Text\n                </label>\n            </div>\n            <div class=\"cursor-pointer p-5 text-icon transition-all hover:text-red-button\" \n                @onclick=\"() => _notifications.Remove(notification)\">\n                CLOSE\n            </div>\n        </div>\n    }\n</div>\n\n@code {\n    private List<Notification> _notifications = [];\n\n    public async void RunNotification(Notification notification)\n    {\n        _notifications.Add(notification);\n        StateHasChanged();\n        await Task.Delay(Constants.Limits.DEFAULT_NOTIFICATION_TIME_IN_MS);\n        if(_notifications.Contains(notification)) {\n            _notifications.Remove(notification);\n            StateHasChanged();\n        }\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/PriorityLabel.razor",
    "content": "@if(Priority.Equals(CardPriority.Normal)) {\n    <div class=\"priority bg-sky-500 text-label-text\">\n        <i class=\"fa fa-flag\"></i>\n        Normal\n    </div>\n} else if(Priority.Equals(CardPriority.Medium)) {\n    <div class=\"priority bg-yellow-500 text-label-text\">\n        <i class=\"fa fa-flag\"></i>\n        Medium\n    </div>\n} else if(Priority.Equals(CardPriority.High)) {\n    <div class=\"priority bg-orange-500 text-label-text\">\n        <i class=\"fa fa-flag\"></i>\n        High\n    </div>\n} else if(Priority.Equals(CardPriority.Critical)) {\n    <div class=\"priority bg-red-500 text-label-text\">\n        <i class=\"fa fa-flag\"></i>\n        Critical\n    </div>\n}\n\n@code {\n    [Parameter]\n    public required CardPriority Priority { get; set; }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/Sortable/SortableList.razor",
    "content": "@using System.Collections.Generic\n@using System.Diagnostics.CodeAnalysis\n@using Microsoft.JSInterop\n\n@inject IJSRuntime JS\n\n@typeparam T\n\n<div data-max-items=\"@MaxItems\" id=\"@Id\" class=\"@Class\" style=\"@Style\">\n    @if (Items != null)\n    {\n        @foreach (var item in Items)\n        {\n            @if (SortableItemTemplate is not null)\n            {\n                @SortableItemTemplate(item)\n            }\n        }\n    }\n    else\n    {\n        <div>Error: The list of items is null</div>\n    }\n</div>\n\n\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/Sortable/SortableList.razor.cs",
    "content": "using System.Diagnostics.CodeAnalysis;\nusing System.Linq.Expressions;\nusing Microsoft.AspNetCore.Components;\nusing Microsoft.JSInterop;\n\nnamespace Ticky.Web.Components.Elements.Sortable\n{\n    public partial class SortableList<T>\n    {\n        private DotNetObjectReference<SortableList<T>>? selfReference;\n\n        [Parameter]\n        public int Animation { get; set; } = 200;\n\n        [Parameter]\n        public string? Filter { get; set; }\n\n        [Parameter]\n        public bool ForceFallback { get; set; } = true;\n\n        [Parameter]\n        public string Group { get; set; } = Guid.NewGuid().ToString();\n\n        [Parameter]\n        public string? Handle { get; set; }\n\n        [Parameter]\n        public string Id { get; set; } = Guid.NewGuid().ToString();\n\n        [Parameter]\n        public int MaxItems { get; set; }\n\n        [Parameter]\n        [AllowNull]\n        public IList<T> Items { get; set; }\n\n        [Parameter]\n        public EventCallback<(\n            string movedItemId,\n            string? targetItemId,\n            string oldColumnId,\n            string newColumnId,\n            double x,\n            double y\n        )> OnRemove { get; set; }\n\n        [Parameter]\n        public EventCallback<(\n            string movedItemId,\n            string? targetItemId,\n            string columnId\n        )> OnUpdate { get; set; }\n\n        [Parameter]\n        public EventCallback OnExceededLimit { get; set; }\n\n        [Parameter]\n        public string? Pull { get; set; }\n\n        [Parameter]\n        public bool Put { get; set; } = true;\n\n        [Parameter]\n        public bool Sort { get; set; } = true;\n\n        [Parameter]\n        public string? Class { get; set; }\n\n        [Parameter]\n        public string? Style { get; set; }\n\n        [Parameter]\n        public string Direction { get; set; } = \"vertical\";\n\n        [Parameter]\n        public RenderFragment<T>? SortableItemTemplate { get; set; }\n\n        public void Dispose() => selfReference?.Dispose();\n\n        [JSInvokable]\n        public async Task OnRemoveJS(\n            string movedItemId,\n            string? targetItemId,\n            string fromId,\n            string toId,\n            double x,\n            double y\n        )\n        {\n            await OnRemove.InvokeAsync((movedItemId, targetItemId, fromId, toId, x, y));\n        }\n\n        [JSInvokable]\n        public async Task OnUpdateJS(string movedItemId, string? targetItemId, string fromId)\n        {\n            await OnUpdate.InvokeAsync((movedItemId, targetItemId, fromId));\n        }\n\n        [JSInvokable]\n        public async Task OnExceededLimitJS() => await OnExceededLimit.InvokeAsync();\n\n        protected override async Task OnAfterRenderAsync(bool firstRender)\n        {\n            if (firstRender)\n            {\n                selfReference = DotNetObjectReference.Create(this);\n                try\n                {\n                    var module = await JS.InvokeAsync<IJSObjectReference>(\n                        \"import\",\n                        \"../Components/Elements/Sortable/SortableList.razor.js\"\n                    );\n\n                    await module.InvokeAsync<string>(\n                        \"init\",\n                        Id,\n                        Group,\n                        Pull,\n                        Put,\n                        Sort,\n                        Handle,\n                        Filter,\n                        selfReference,\n                        ForceFallback,\n                        Direction,\n                        Animation\n                    );\n                }\n                catch (JSException ex)\n                {\n                    Console.WriteLine($\"Sortable init skipped for Id={Id}: {ex.Message}\");\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/Sortable/SortableList.razor.css",
    "content": "/* \n  you need the ::deep identifier if you are using scoped styles like this\n  because scoped styles are only applied to markup in the component, not\n  to the markup inside the render fragment.\n*/\n\n::deep .sortable-ghost {\n  visibility: hidden;\n}\n\n::deep .sortable-fallback {\n  opacity: 1 !important\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/Sortable/SortableList.razor.js",
    "content": "export function init(id, group, pull, put, sort, handle, filter, component, forceFallback, direction, animation) {\n    const DEBUG_MODE = false;\n\n    if (DEBUG_MODE) {\n        console.log(\"Init for Id:\", id);\n    }\n\n    let htmlElement = document.getElementById(id);\n\n    if (!htmlElement) {\n        if (DEBUG_MODE) console.warn(\"Sortable init: element with id '\" + id + \"' not found. Aborting init.\");\n        return;\n    }\n\n    var sortable = new Sortable(htmlElement, {\n        animation: animation,\n        delayOnTouchOnly: true,\n        delay: 200,\n        group: {\n            name: group,\n            pull: pull || true,\n            put: put\n        },\n        filter: filter || undefined,\n        sort: sort,\n        forceFallback: forceFallback,\n        handle: handle || undefined,\n        direction: direction,\n        onUpdate: (event) => {\n            let customChildNodes = Array.from(event.to.childNodes).filter(node => node.tagName === 'DIV');\n\n            if (customChildNodes.length === 1) {\n                if (DEBUG_MODE)\n                    console.log('ignoring move because moved into the same place')\n                return\n            }\n\n            let movedCard = event.item\n            let movedCardId = movedCard.id\n\n            let cardBelow = customChildNodes[event.newIndex + 1]\n            let cardBelowId = null\n\n            if (cardBelow)\n                cardBelowId = cardBelow.id\n\n            if (DEBUG_MODE) {\n                console.log(event)\n                console.log(\"onUpdate item:\");\n                console.log(event.item);\n                console.log('event from: ', event.from)\n                console.log('event to: ', event.to)\n                console.log('event oldIndex: ', event.oldIndex)\n                console.log('event newIndex: ', event.newIndex)\n                console.log('event to childNodes: ', customChildNodes)\n                console.log('movedCard: ', movedCard)\n                console.log('insert before: ', cardBelow)\n                console.log('movedCardId: ', movedCardId)\n                console.log('insert before Id: ', cardBelowId)\n            }\n\n            component.invokeMethodAsync('OnUpdateJS', movedCardId, cardBelowId, event.from.id);\n        },\n        onRemove: (event) => {\n            let customFromChildNodes = Array.from(event.from.childNodes).filter(node => node.tagName === 'DIV');\n            let customToChildNodes = Array.from(event.to.childNodes).filter(node => node.tagName === 'DIV');\n\n            let movedCard = customToChildNodes[event.newIndex]\n            let cardBelow = customToChildNodes[event.newIndex + 1]\n            let cardBelowId = null\n            let movedCardId = movedCard.id\n\n            if (cardBelow)\n                cardBelowId = cardBelow.id\n\n            if (DEBUG_MODE) {\n                console.log(event)\n                console.log(\"onRemove item:\");\n                console.log(event.item);\n                console.log('event from: ', event.from)\n                console.log('event to: ', event.to)\n                console.log('event oldIndex: ', event.oldIndex)\n                console.log('event newIndex: ', event.newIndex)\n                console.log('event to childNodes: ', customToChildNodes)\n                console.log('moved card: ', movedCard)\n                console.log('card below inserted: ', cardBelow)\n                console.log('moved card ID: ', movedCardId)\n                console.log('card below inserted ID: ', cardBelowId)\n            }\n\n            if (event.to.dataset.maxItems != 0 && customToChildNodes.length-1 >= event.to.dataset.maxItems) {\n                event.item.remove();\n\n                event.from.insertBefore(event.item, customFromChildNodes[event.oldIndex]);\n                component.invokeMethodAsync('OnExceededLimitJS');\n                return;\n            }\n\n            component.invokeMethodAsync('OnRemoveJS', movedCardId, cardBelowId, event.from.id, event.to.id, event.originalEvent.clientX / event.originalEvent.view.outerWidth, event.originalEvent.clientY / event.originalEvent.view.outerHeight);\n        },\n        onMove: (event) => {\n            // This event fires continually as you drag.\n            // You typically wouldn't do DOM manipulation here.\n            // It's useful for preventing drops, etc.\n            // If you return false, the item cannot be dropped at that position.\n            // return !event.related.classList.contains('no-drop');\n            return true; // Allow all moves by default\n        }\n    });\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/Spinner.razor",
    "content": "<div data-small='@Small.ToString()' class=\"element-spinner-wrapper @Class\">\n    <div class=\"element-spinner\">\n    </div>\n</div>\n\n@code {\n    [Parameter]\n    public string? Class { get; set; }\n\n    [Parameter]\n    public bool Small { get; set; }\n}"
  },
  {
    "path": "Ticky.Web/Components/Elements/SubtaskView.razor",
    "content": "@using Microsoft.JSInterop\n@using Microsoft.EntityFrameworkCore\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject ILogger<SubtaskView> _logger\n\n@inherits NotifiableBase\n\n<div id=\"@Subtask.Id\" class=\"flex flex-row flex-wrap items-center gap-2 text-sm font-normal\">\n    <i class=\"fa fa-grip-lines-vertical drag-toggle icon-button cursor-move text-icon\" title=\"Drag to reorder subtask\"></i>\n    <input id=\"subtask_checkbox_@Subtask.Id\" type=\"checkbox\" checked=\"@Subtask.Completed\" @onchange=\"OnSubtaskStatusChanged\" />\n    <label class=\"min-w-0 break-normal break-words\" for=\"subtask_checkbox_@Subtask.Id\">@Subtask.Text</label>\n\n    @if (Subtask.Assignees.Any())\n    {\n        <div class=\"ml-4 flex flex-row\">\n            @{\n        var i = 0;\n                foreach (var assignee in Subtask.Assignees.OrderBy(x => x.DisplayName))\n        {\n            var avatarId = $\"subtask_assignee_{Subtask.Id}_{i}\";\n                    <div id=@avatarId class=\"avatar stack-avatars\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@assignee.ProfilePictureFileName');\" @onclick=\"() => MainLayout.UserInfoModal?.Open(avatarId, assignee.Id)\"></div>\n            i++;\n        }\n            }\n        </div>\n    }\n\n    <i @ref=_assigneesTrigger class=\"fa fa-user edit-icon\" @onclick='() => AssigneesModal?.Open(_assigneesTrigger, Subtask, Members)' title=\"Add/remove assignees\"></i>\n    <i id=\"subtask_edit_@Subtask.Id\" class=\"fa fa-pencil edit-icon\" @onclick='() => EditSubtaskModal?.Open($\"subtask_edit_{Subtask.Id}\", Subtask)' title=\"Edit subtask\"></i>\n    <i class=\"fa fa-trash-can edit-icon !text-red-button hover:!text-red-button-hover\" @onclick=\"DeleteSubtask\" title=\"Delete subtask\"></i>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    [Parameter]\n    public required Subtask Subtask { get; set; }\n\n    [Parameter]\n    public EditSubtaskModal? EditSubtaskModal { get; set; }\n\n    [Parameter]\n    public List<User> Members { get; set; } = [];\n\n    [Parameter]\n    public EventCallback UpdateCard { get; set; }\n\n    [Parameter]\n    public AssigneesModal? AssigneesModal { get; set; }\n\n    private ElementReference? _assigneesTrigger;\n\n    private async Task OnSubtaskStatusChanged(ChangeEventArgs e)\n    {\n\ttry\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n            var target = await db.Subtasks\n                .Include(x => x.Card)\n                    .ThenInclude(x => x.Activities)\n                .FirstOrDefaultAsync(x => x.Id.Equals(Subtask.Id));\n\n            if (target is null)\n                return;\n\n            target.Completed = e.Value is not null ? (bool)e.Value : false;\n\n            target.Card.Activities.Add(new Activity\n            {\n                Text = $\"<b>marked</b> the subtask <b>{target.Text}</b> as <b>{(target.Completed ? \"completed\" : \"to be done\")}</b>\",\n                UserId = _user.Id,\n                CardId = target.CardId,\n            });\n\n            await db.SaveChangesAsync();\n            await UpdateCard.InvokeAsync();\n        }\n        catch (Exception ex)\n        {\n            _logger?.LogError(ex, \"Failed to change subtask status.\");\n            _mainLayout.RunNotification(new Notification(\"Failed to update subtask status.\", NotificationType.Fail));\n        }\n    }\n\n    private async Task DeleteSubtask()\n    {\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var sub = await db.Subtasks\n                .Include(x => x.Card)\n                    .ThenInclude(x => x.Activities)\n                .FirstOrDefaultAsync(x => x.Id.Equals(Subtask.Id));\n\n            if (sub is null)\n                return;\n\n            sub.Card.Activities.Add(new Activity\n            {\n                Text = $\"<b>deleted</b> subtask <b>{sub.Text}</b>\",\n                UserId = _user.Id,\n                CardId = sub.CardId,\n            });\n\n            db.Subtasks.Remove(sub);\n\n            var card = await db.Cards.Include(x => x.Subtasks).FirstOrDefaultAsync(x => x.Id.Equals(sub.CardId));\n            if (card is not null)\n            {\n                IndexHelper.FixIndices(card.Subtasks);\n            }\n\n            await db.SaveChangesAsync();\n            await UpdateCard.InvokeAsync();\n        }\n        catch (Exception ex)\n        {\n            _logger?.LogError(ex, \"Failed to delete subtask.\");\n            _mainLayout.RunNotification(new Notification(\"Failed to delete subtask.\", NotificationType.Fail));\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/TimeSelect.razor",
    "content": "@using Microsoft.AspNetCore.Components\n@using Microsoft.AspNetCore.Components.Forms\n\n<InputSelect class=\"form-control\" TValue=string Value=\"_selectedValue\" ValueChanged=\"@(OnValueChanged)\" ValueExpression=\"@(() => _selectedValue)\">\n    @foreach (var time in GetTimeOptions())\n    {\n        <option value=\"@time\">@time</option>\n    }\n</InputSelect>\n\n@code {\n    private string _selectedValue = string.Empty;\n\n    [Parameter]\n    public string Value { get; set; } = string.Empty;\n\n    [Parameter]\n    public EventCallback<string> ValueChanged { get; set; }\n\n    private static List<string>? _timeOptions;\n\n    protected override void OnParametersSet()\n    {\n        if (_selectedValue != Value)\n            _selectedValue = Value;\n    }\n\n    private async Task OnValueChanged(string value)\n    {\n        if (_selectedValue == value)\n            return;\n\n        _selectedValue = value;\n        await ValueChanged.InvokeAsync(value);\n    }\n\n    private static List<string> GetTimeOptions()\n    {\n        if(_timeOptions != null)\n            return _timeOptions;\n\n        var options = new List<string>();\n        var start = TimeSpan.Zero;\n        var end = new TimeSpan(23, 45, 0);\n        for (var time = start; time <= end; time = time.Add(TimeSpan.FromMinutes(15)))\n        {\n            options.Add(time.ToString(@\"hh\\:mm\"));\n        }\n        _timeOptions = options;\n        return options;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Elements/Tooltip.razor",
    "content": "<div class=\"tooltip-wrapper\">\n    <span class=\"tooltip-span\">@Text</span>\n    @ChildContent\n</div>\n\n@code {\n    [Parameter] \n    public required RenderFragment ChildContent { get; set; }\n\n    [Parameter] \n    public required string Text { get; set; }\n}"
  },
  {
    "path": "Ticky.Web/Components/Layout/MainLayout.razor",
    "content": "@inherits LayoutComponentBase\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject NavigationManager _navigationManager\n\n<PageTitle>@Constants.APP_NAME</PageTitle>\n\n<CascadingValue Name=\"@Constants.CascadingParameters.CurrentAccount\" Value=\"@_user\">\n    <Notifications @ref=\"_notifications\" />\n    <CascadingValue Name=\"@Constants.CascadingParameters.MainLayout\" Value=\"this\">\n        <div class=\"h-visible-screen\">\n            <NavMenu/>\n\n            <main class=\"overflow-x-clip overflow-y-auto\">\n                @if(_user is null)\n                {\n                    <Spinner/>\n                } else {\n                    @Body\n                }\n            </main>\n        </div>\n\n        <div id=\"blazor-error-ui\" data-nosnippet>\n            An unhandled error has occurred.\n            <a href=\".\" class=\"reload\">Reload</a>\n            <span class=\"dismiss\">🗙</span>\n        </div>\n        <UserInfoModal @ref=\"UserInfoModal\"/>\n        <InformationModal @ref=\"_informationModal\"/>\n    </CascadingValue>\n</CascadingValue>\n\n@code {\n    [CascadingParameter]\n    private Task<AuthenticationState>? AuthenticationStateTask { get; set; }\n\n    private Notifications? _notifications { get; set; }\n\n    private User? _user { get; set; }\n\n    public UserInfoModal? UserInfoModal { get; set; }\n\n    private InformationModal? _informationModal;\n\n    protected override async Task OnParametersSetAsync()\n    {\n        if (AuthenticationStateTask != null)\n        {\n            var authState = await AuthenticationStateTask;\n\n            if (authState.User?.Identity?.IsAuthenticated == true)\n            {\n                using var db = _dbContextFactory.CreateDbContext();\n                _user = await db.Users\n                    .AsNoTracking()\n                    .Include(x => x.ProjectMemberships)\n                    .Include(x => x.BoardMemberships)\n                    .SingleOrDefaultAsync(x => x.Email != null && x.Email.Equals(authState.User.Identity.Name));\n\n                if (_user is not null) \n                {\n                    var credentialsSettings = \"/settings/3\";\n\n                    if (_user.NeedsNewCredentials && !_navigationManager.Uri.EndsWith(credentialsSettings))\n                    {\n                        _navigationManager.NavigateTo(credentialsSettings);\n                    }\n\n                    StateHasChanged();\n\n                    if(_informationModal is not null)\n                        await _informationModal.OpenIfNeeded();\n\n                    return;\n                }\n\n                _navigationManager.NavigateTo(Constants.Mappings.LOGOUT_PATH, true);\n            }\n        }\n\n        var currentRelative = _navigationManager.ToBaseRelativePath(_navigationManager.Uri);\n        var returnUrl = \"/\" + currentRelative;\n        var loginWithReturn = $\"{Constants.Mappings.LOGIN_PATH}?returnUrl={Uri.EscapeDataString(returnUrl)}\";\n        _navigationManager.NavigateTo(loginWithReturn, true);\n    }\n\n    public void RunNotification(Notification notification)\n    {\n        _notifications?.RunNotification(notification);\n    }\n\n    public async Task UpdateRecentBoard()\n    {\n        if(_user is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n        _user = await db.Users\n            .AsNoTracking()\n            .Include(x => x.ProjectMemberships)\n            .Include(x => x.BoardMemberships)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        StateHasChanged();\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Layout/NavMenu.razor",
    "content": "@implements IDisposable\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject IJSRuntime _js\n@inject NavigationManager _navigationManager\n@inject SearchService _searchService\n\n<nav id=\"nav-menu\" class=\"z-10 flex w-full items-center justify-center bg-card-bg px-10 py-2\">\n    <!-- Desktop version -->\n    <div class=\"hidden w-full flex-row justify-center self-center lg:flex\">\n        <div class=\"mr-auto flex flex-row items-center gap-5\">\n            <NavLink href=\"/\">\n                <img height=\"32\" width=\"32\" src='@Assets[\"/images/ticky.png\"]' alt=\"Ticky app logo\"/>\n            </NavLink>\n            <input @ref=\"_triggerElement\" class=\"w-80 rounded-2xl bg-search-bar p-2 text-center text-xs\" type=\"search\"\n                   placeholder=\"Search for tasks ...\" @oninput=\"UpdateSearchTerm\"\n                   @onclick='OpenSearchResults' @onclick:stopPropagation=true/>\n        </div>\n        <div @ref=\"_dropdownElement\" class=\"dropdown absolute top-0 left-0 z-10 hidden min-w-80 bg-modal shadow\">\n            @if(_isLoading)\n            {\n                <Spinner Class=\"py-2\"/>\n            } else if (_resultCards.Count == 0) \n            {\n                <div class=\"px-3 py-2 text-xs\">\n                    No results have been found.\n                </div>\n            } else {\n                foreach(var result in _resultCards) {\n                    <div class=\"flex cursor-pointer flex-col justify-between px-3 py-2 text-xs hover:bg-dropdown-option\" @onclick='() => GoToCard(result.Column.BoardId, result.Id)'>\n                        <div class=\"flex flex-row justify-between gap-3\">\n                            <label class=\"cursor-pointer whitespace-nowrap\">@result.Column.Board.Code-@result.Number</label>\n                            <label class=\"cursor-pointer truncate whitespace-nowrap\">@result.Name</label>\n                        </div>\n                        <label class=\"text-2xs cursor-pointer font-light\">Project @result.Column.Board.Project.Name — @result.Column.Board.Name</label>\n                    </div>\n                }\n            }\n        </div>\n        <div class=\"mr-auto grid\">\n            <div class=\"nav-links\" style=\"grid-column: 1; grid-row: 1;\">\n                <NavLink class=\"nav-link\" Match=\"NavLinkMatch.All\" href=\"/\">\n                    Home\n                </NavLink>\n                @if (_user?.LastVisitedBoardId is not null)\n                {\n                    <NavLink class=\"nav-link\" href=@($\"{Constants.Mappings.BOARD_PATH}/{_user?.LastVisitedBoardId}\")>\n                        Recent board\n                    </NavLink>\n                }\n                <AuthorizeView Policy=\"@Constants.Policies.RequireAdmin\">\n                    <NavLink class=\"nav-link\" href=\"/admin\">\n                        Admin Panel\n                    </NavLink>\n                </AuthorizeView>\n                <NavLink class=\"nav-link\" href=\"@Constants.Mappings.LOGOUT_PATH\">\n                    Log out\n                </NavLink>\n            </div>\n            <div class=\"flex w-100 flex-col justify-end\" style=\"grid-column: 1; grid-row: 1;\">\n                <div id=\"nav-button-underline\" class=\"h-0.5 w-0 bg-primary transition-all ease-in-out\"></div>\n            </div>\n        </div>\n        <div class=\"ml-auto flex flex-row items-center gap-5\">\n            <span class=\"fa fa-circle-half-stroke cursor-pointer text-2xl text-nav-link transition-all hover:text-nav-link-hover\" onclick=\"switchTheme()\" title=\"Switch theme\"></span>\n            <NavLink href=\"/settings\">\n                <div class=\"avatar avatar-border\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_user?.ProfilePictureFileName');\"></div>\n            </NavLink>\n        </div>\n    </div>\n\n    <!-- Mobile version -->\n    <div class=\"flex w-full flex-row items-center justify-between text-nav-link lg:hidden\">\n        <SearchModal @ref=\"_searchModal\"/>\n\n        <NavLink href=\"/\">\n            <img height=\"32\" width=\"32\" src='@Assets[\"/images/ticky.png\"]' alt=\"Ticky app logo\" />\n        </NavLink>\n        @if (_user?.LastVisitedBoardId is not null)\n        {\n            <NavLink class=\"nav-link\" Match=\"NavLinkMatch.All\" href=@($\"{Constants.Mappings.BOARD_PATH}/{_user?.LastVisitedBoardId}\")>\n                <span class=\"fa fa-briefcase\" title=\"Recent board\"></span>\n            </NavLink>\n        }\n        <div class=\"nav-link\" @onclick=\"() => _searchModal?.Open()\">\n            <span class=\"fa fa-magnifying-glass\" title=\"Search\"></span>\n        </div>\n        <AuthorizeView Policy=\"@Constants.Policies.RequireAdmin\">\n            <NavLink class=\"nav-link\" href=\"/admin\">\n                <span class=\"fa fa-users\" title=\"Admin panel\"></span>\n            </NavLink>\n        </AuthorizeView>\n\n        <Dropdown Actions='new() {\n            { \"User settings\", () => _navigationManager.NavigateTo(\"/settings\") },\n            { \"Switch theme\", () => _js.InvokeVoidAsync(\"switchTheme\") },\n            { \"Log out\", () => _navigationManager.NavigateTo(Constants.Mappings.LOGOUT_PATH, true) },\n        }'>\n            <div class=\"avatar avatar-border\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_user?.ProfilePictureFileName');\"></div>\n        </Dropdown>\n    </div>\n</nav>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    private Timer? _timer;\n    private string? _searchTerm;\n    private bool _isLoading;\n\n    private List<Card> _resultCards = [];\n\n    private ElementReference? _triggerElement;\n    private ElementReference? _dropdownElement;\n    private SearchModal? _searchModal;\n\n    protected override void OnAfterRender(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        StateHasChanged();\n\n        _timer = new Timer(Constants.Limits.DEBOUNCE_TIME_IN_MS);\n        _timer.Stop();\n        _timer.Elapsed += Filter;\n        _timer.AutoReset = false;\n    }\n\n    private void UpdateSearchTerm(ChangeEventArgs e)\n    {\n        _searchTerm = e.Value as string;\n\n        _timer?.Stop();\n        _timer?.Start();\n\n        _isLoading = true;\n        StateHasChanged();\n    }\n\n    private async Task GoToCard(int boardId, int cardId)\n    {\n        _navigationManager.NavigateTo($\"{Constants.Mappings.BOARD_PATH}/{boardId}/{cardId}\");\n        await _js.InvokeVoidAsync(\"closeDropdowns\");\n    }\n\n    private async Task OpenSearchResults()\n    {\n        await _js.InvokeVoidAsync(\"openDropDownOnElementPosition\", _dropdownElement, _triggerElement);\n    }\n\n    private async void Filter(Object? obj = null, ElapsedEventArgs? e = null)\n    {\n        _resultCards = await _searchService.SearchAsync(_searchTerm, _user);\n        _isLoading = false;\n        await InvokeAsync(StateHasChanged);\n    }\n\n    void IDisposable.Dispose()\n        => _timer?.Dispose();\n}"
  },
  {
    "path": "Ticky.Web/Components/Pages/Abstractions/NotifiableBase.razor",
    "content": "@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    protected MainLayout MainLayout { get; set; } = default!;\n\n    protected async Task RunNotification(Type type, OperationType operationType) \n    {\n        await HandleUpdate();\n        MainLayout.RunNotification(new Notification($\"{type.Name.ToFriendlyName()} {operationType.GetDisplayName()} successfully.\"));\n    }\n\n    protected virtual Task HandleUpdate()\n    {\n        StateHasChanged();\n        return Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/AdminPanel.razor",
    "content": "@page \"/admin\"\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject ILogger<BoardSettings> _logger\n@inherits NotifiableBase\n@attribute [Authorize(Policy = Constants.Policies.RequireAdmin)]\n\n<AddUserModal @ref=\"_addUserModal\" OnSubmit=\"() => RunNotification(typeof(User), OperationType.Added)\" />\n<EditUserModal @ref=\"_editUserModal\" OnSubmit=\"() => RunNotification(typeof(User), OperationType.Edited)\" />\n<DeleteConfirmationDialog T=\"User\" @ref=\"_deleteUserModal\" OnConfirmed=\"HandleUpdate\" />\n\n<PageTitle>Admin Panel - @Constants.APP_NAME</PageTitle>\n\n<div class=\"w-full\">\n    <section class=\"flex w-full max-w-4xl flex-grow flex-col gap-5 overflow-y-auto px-12 py-14\">\n        <header class=\"flex flex-row justify-between text-2xl font-bold\">\n            App settings\n        </header>\n\n        <section\n            class=\"flex w-full flex-row flex-wrap items-center justify-start gap-1 rounded-lg border border-tab-outline px-1 py-1 text-sm\">\n            <div data-active='@(_tab == 1 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"() => GoToTab(1)\">Users</div>\n        </section>\n\n        <section class=\"flex w-full flex-col divide-y divide-tab-outline\">\n            @if (_tab == 1)\n            {\n                <div class=\"flex flex-row items-center justify-between\">\n                    <div class=\"flex flex-col py-5\">\n                        <label class=\"font-bold\">Users</label>\n                        <label class=\"text-sm opacity-70\">Create, edit and delete user accounts.</label>\n                    </div>\n                    <button class=\"px-5\" @onclick=\"() => _addUserModal?.Open()\">Create a user</button>\n                </div>\n\n                @if (_users is null)\n                {\n                    <Spinner/>\n                } else {\n                    <div class=\"flex flex-col flex-wrap items-center gap-5 overflow-y-auto pt-5 md:flex-row\">\n                        @foreach (var user in _users)\n                        {\n                            <div class=\"flex w-full flex-col items-center gap-3 rounded bg-card-bg pt-5 shadow-lg md:w-64\">\n                                <img class=\"avatar !h-32 !w-32\" src=\"@Constants.ACCESS_UPLOADED_IMAGES_PATH/@user.ProfilePictureFileName\" />\n                                <div class=\"flex flex-col items-center px-5 pb-3 select-none\">\n                                    <div class=\"font-semibold\">@user.DisplayName</div>\n                                    <div class=\"text-sm\">@user.Email</div>\n                                </div>\n                                <div class=\"bg-card-diff-bg flex w-full flex-col items-center gap-3 px-5 py-3\">\n                                    <button class=\"w-full\" @onclick=\"() => _editUserModal?.Open(user.Id)\">Edit</button>\n                                    <button class=\"w-full !bg-red-button hover:!bg-red-button-hover\" @onclick=\"() => _deleteUserModal!.OpenDialog(user)\">Delete</button>\n                                </div>\n                            </div>\n                        }\n                    </div>\n                }\n\n            }\n        </section>\n    </section>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public int Id { get; set; } = default!;\n\n    private int _tab = 1;\n\n    private List<User>? _users;\n    private AddUserModal? _addUserModal;\n    private EditUserModal? _editUserModal;\n    private DeleteConfirmationDialog<User>? _deleteUserModal;\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        await HandleUpdate();\n    }\n\n    protected override async Task HandleUpdate()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        _users = await db.Users\n            .AsNoTracking()\n            .ToListAsync();\n\n        if (_users is null)\n            return;\n\n        await base.HandleUpdate();\n    }\n\n    private void GoToTab(int tabNumber) \n    {\n        _tab = tabNumber;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ChangePassword.cshtml",
    "content": "@page\n@model ChangePasswordModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card\">\n        <div class=\"flex flex-col gap-1\">\n            <h1 class=\"text-3xl font-extrabold\">Password change</h1>\n            <label class=\"opacity-40\">Please provide a new password</label>\n        </div>\n        @using (Html.BeginForm(FormMethod.Post, true, new { @class = \"auth-form\" }))\n        {\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.Code, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.Code, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.Code)\n            </div>\n\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.Password, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.Password, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.Password)\n            </div>\n\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.ConfirmPassword, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.ConfirmPassword, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.ConfirmPassword)\n            </div>\n\n            @Html.AntiForgeryToken()\n\n            <button class=\"auth-button\" type=\"submit\">Change</button>\n            <div class=\"flex flex-row items-center justify-center gap-1\">\n                <div class=\"text-auth-bottom-text text-xs font-normal\">Not needed anymore?</div>\n                <a class=\"auth-link\" href=\"/auth/login\">Log in</a>\n            </div>\n        }\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ChangePassword.cshtml.cs",
    "content": "﻿namespace Ticky.Web.Pages.Auth;\n\npublic class ChangePasswordModel : PageModel\n{\n    private readonly DataContext _dataContext;\n    private readonly UserManager<User> _userManager;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = new();\n\n    public ChangePasswordModel(DataContext dataContext, UserManager<User> userManager)\n    {\n        _dataContext = dataContext;\n        _userManager = userManager;\n    }\n\n    public IActionResult OnGet()\n    {\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPostAsync()\n    {\n        if (ModelState.IsValid)\n        {\n            var targetCode = await _dataContext\n                .Codes.Include(x => x.User)\n                .FirstOrDefaultAsync(x => x.Value.Equals(Input.Code));\n\n            if (targetCode is not null)\n            {\n                await _userManager.ResetPasswordAsync(\n                    targetCode.User,\n                    await _userManager.GeneratePasswordResetTokenAsync(targetCode.User),\n                    Input.Password\n                );\n                _dataContext.Codes.Remove(targetCode);\n                await _dataContext.SaveChangesAsync();\n                return LocalRedirect(\"/auth/passwordchanged\");\n            }\n\n            ModelState.AddModelError(\n                $\"{nameof(Input)}.{nameof(Input.Code)}\",\n                \"The provided code was not correct.\"\n            );\n        }\n\n        return Page();\n    }\n\n    public class InputModel\n    {\n        [Required(AllowEmptyStrings = false)]\n        [RegularExpression(\"[1-9]{3}-[1-9]{3}\")]\n        [Display(Name = \"Confirmation code from the e-mail we sent you\", Prompt = \"123-456\")]\n        public string Code { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        [DataType(DataType.Password)]\n        [Display(Name = \"New password\", Prompt = \"●●●●●●●●●●●\")]\n        public string Password { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        [DataType(DataType.Password)]\n        [Display(Name = \"Repeat new password\", Prompt = \"●●●●●●●●●●●\")]\n        [Compare(\"Password\", ErrorMessage = \"The passwords must match.\")]\n        public string ConfirmPassword { get; set; } = string.Empty;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ConfirmMail.cshtml",
    "content": "﻿@page\n@model ConfirmMailModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card\">\n        <div class=\"flex flex-col gap-1\">\n            <h1 class=\"text-3xl font-extrabold\">Confirm e-mail</h1>\n            <label class=\"opacity-40\">We have sent a code to the provided e-mail address</label>\n        </div>\n        @using (Html.BeginForm(FormMethod.Post, true, new { @class = \"auth-form\" }))\n        {\n            @Html.HiddenFor(model => model.Input.EmailAddress)\n\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.Code, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.Code, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.Code)\n            </div>\n\n            @Html.AntiForgeryToken()\n\n            <button class=\"auth-button\" type=\"submit\">Submit</button>\n            <div class=\"flex flex-row items-center justify-center gap-1\">\n                <div class=\"text-auth-bottom-text text-xs font-normal\">Wrong e-mail?</div>\n                <a class=\"auth-link\" href=\"/auth/register\">Back to creating an account</a>\n            </div>\n        }\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ConfirmMail.cshtml.cs",
    "content": "namespace Ticky.Web.Pages.Auth;\n\npublic class ConfirmMailModel : PageModel\n{\n    private readonly DataContext _dataContext;\n    private readonly SignInManager<User> _signInManager;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = new();\n\n    public ConfirmMailModel(DataContext dataContext, SignInManager<User> signInManager)\n    {\n        _dataContext = dataContext;\n        _signInManager = signInManager;\n    }\n\n    public IActionResult OnGet(string email)\n    {\n        Input.EmailAddress = email;\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPostAsync()\n    {\n        if (ModelState.IsValid)\n        {\n            var targetUser = await _dataContext\n                .Users.Where(x => Input.EmailAddress.Equals(x.Email))\n                .Include(x => x.EmailVerificationCode)\n                .FirstOrDefaultAsync(x =>\n                    x.EmailVerificationCode != null\n                    && Input.Code.Equals(x.EmailVerificationCode.Value)\n                );\n\n            if (targetUser is not null)\n            {\n                targetUser.EmailConfirmed = true;\n                _dataContext.Update(targetUser);\n                _dataContext.Codes.Remove(targetUser.EmailVerificationCode!);\n\n                await _dataContext.SaveChangesAsync();\n\n                await _signInManager.SignInAsync(targetUser, true);\n\n                return LocalRedirect(\"/auth/mailconfirmed\");\n            }\n\n            ModelState.AddModelError(\n                $\"{nameof(Input)}.{nameof(Input.Code)}\",\n                \"The provided code was not valid.\"\n            );\n        }\n\n        return Page();\n    }\n\n    public class InputModel\n    {\n        [Required(AllowEmptyStrings = false)]\n        [RegularExpression(\"[1-9]{3}-[1-9]{3}\")]\n        [Display(Name = \"Confirmation code from the received e-mail\", Prompt = \"123-456\")]\n        public string Code { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        public string EmailAddress { get; set; } = string.Empty;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ForgotPassword.cshtml",
    "content": "﻿@page\n@model ForgotPasswordModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card\">\n        <div class=\"flex flex-col gap-1\">\n            <h1 class=\"text-3xl font-extrabold\">Forgot your password?</h1>\n            @if (Constants.SMTP_ENABLED)\n            {\n                <label class=\"opacity-40\">Don't worry, we can help.</label>\n            } else\n            {\n                <label class=\"opacity-40\">Reach out to an administrator to get it reset.</label>\n            }\n        </div>\n        @if(Constants.SMTP_ENABLED) \n        {\n            @using (Html.BeginForm(FormMethod.Post, true, new { @class = \"auth-form\" }))\n            {\n                <div class=\"auth-inp-label\">\n                    @Html.LabelFor(model => model.Input.EmailAddress, new { @class = \"auth-label\" })\n                    @Html.EditorFor(model => model.Input.EmailAddress, new { htmlAttributes = new { @class = \"auth-input\" } })\n                    @Html.ValidationMessageFor(model => model.Input.EmailAddress)\n                </div>\n\n                @Html.AntiForgeryToken()\n\n                <button class=\"auth-button\" type=\"submit\">Submit</button>\n            }\n        } else\n        {\n            <div class=\"flex flex-row items-center justify-center gap-1\">\n                <div class=\"text-auth-bottom-text text-xs font-normal\">Not needed anymore?</div>\n                <a class=\"auth-link\" href=\"/auth/login\">Log in</a>\n            </div>\n        }\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/ForgotPassword.cshtml.cs",
    "content": "namespace Ticky.Web.Pages.Auth;\n\npublic class ForgotPasswordModel : PageModel\n{\n    private readonly DataContext _dataContext;\n    private readonly CodeService _codeService;\n    private readonly EmailService _emailService;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = new();\n\n    public ForgotPasswordModel(\n        DataContext dataContext,\n        CodeService codeService,\n        EmailService emailService\n    )\n    {\n        _dataContext = dataContext;\n        _codeService = codeService;\n        _emailService = emailService;\n    }\n\n    public IActionResult OnGet()\n    {\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPostAsync()\n    {\n        if (ModelState.IsValid)\n        {\n            var targetUser = await _dataContext.Users.FirstOrDefaultAsync(x =>\n                Input.EmailAddress.Equals(x.Email)\n            );\n\n            if (targetUser is not null)\n            {\n                await _emailService.SendForgottenPasswordCodeEmailAsync(\n                    Input.EmailAddress,\n                    await _codeService.CreateCodeAsync(targetUser, CodePurpose.ForgottenPassword)\n                );\n                return LocalRedirect(\"/auth/changepassword\");\n            }\n\n            ModelState.AddModelError(\n                $\"{nameof(Input)}.{nameof(Input.EmailAddress)}\",\n                \"The provider e-mail address is not linked to any existing account.\"\n            );\n        }\n\n        return Page();\n    }\n\n    public class InputModel\n    {\n        [Display(Name = \"E-mail address of your account\", Prompt = \"email@gmail.com\")]\n        [Required(AllowEmptyStrings = false)]\n        [EmailAddress]\n        public string EmailAddress { get; set; } = string.Empty;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Login.cshtml",
    "content": "﻿@page\n@model LoginModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card\">\n        <div class=\"flex flex-col gap-1\">\n            <h1 class=\"text-3xl font-extrabold\">Hey there!</h1>\n            <label class=\"opacity-40\">Use your credentials to log in</label>\n        </div>\n        @using(Html.BeginForm(FormMethod.Post, true, new { @class = \"auth-form\" })) \n        {\n            @if(!string.IsNullOrEmpty(Model.ReturnUrl)) \n            {\n                <input type=\"hidden\" name=\"returnUrl\" value=\"@Model.ReturnUrl\" />\n            }\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.Email, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.Email, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.Email)\n            </div>\n            <div class=\"auth-inp-label\">\n                @Html.LabelFor(model => model.Input.Password, new { @class = \"auth-label\" })\n                @Html.EditorFor(model => model.Input.Password, new { htmlAttributes = new { @class = \"auth-input\" } })\n                @Html.ValidationMessageFor(model => model.Input.Password)\n                <a class=\"auth-link text-end\" href=\"/auth/forgotpassword\">Forgotten password?</a>\n            </div>\n\n            @Html.AntiForgeryToken()\n\n            <button class=\"auth-button\" type=\"submit\">Log in</button>\n            <div class=\"flex flex-row items-center justify-center gap-1\">\n                <div class=\"text-auth-bottom-text text-xs font-normal\">Don't own an account yet?</div>\n                <a class=\"auth-link\" href=\"/auth/register\">Create one!</a>\n            </div>\n        }\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Login.cshtml.cs",
    "content": "﻿using System.ComponentModel.DataAnnotations;\nusing Microsoft.AspNetCore.Identity;\n\nnamespace Ticky.Web.Pages.Auth;\n\npublic class LoginModel : PageModel\n{\n    private readonly SignInManager<User> _signInManager;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = new();\n    public string ReturnUrl { get; set; } = string.Empty;\n\n    public LoginModel(SignInManager<User> signInManager)\n    {\n        _signInManager = signInManager;\n    }\n\n    public IActionResult OnGet(string? returnUrl = null)\n    {\n        ReturnUrl = returnUrl ?? Url.Content(\"~/\");\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPostAsync(string? returnUrl = null)\n    {\n        if (ModelState.IsValid)\n        {\n            var result = await _signInManager.PasswordSignInAsync(\n                Input.Email,\n                Input.Password,\n                true,\n                lockoutOnFailure: false\n            );\n\n            if (result.Succeeded)\n                return LocalRedirect(returnUrl ?? Url.Content(\"~/\"));\n            else\n                ModelState.AddModelError(\n                    $\"{nameof(Input)}.{nameof(Input.Email)}\",\n                    \"The provided e-mail/password combination does not exist.\"\n                );\n        }\n\n        return Page();\n    }\n\n    public class InputModel\n    {\n        [Required]\n        [EmailAddress]\n        [Display(Name = \"E-mail address\", Prompt = \"sample@email.com\")]\n        public string Email { get; set; } = string.Empty;\n\n        [Required]\n        [DataType(DataType.Password)]\n        [Display(Name = \"Password\", Prompt = \"●●●●●●●●●●●\")]\n        public string Password { get; set; } = string.Empty;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Logout.cshtml",
    "content": "@page\n@attribute [IgnoreAntiforgeryToken]\n@inject SignInManager<User> SignInManager\n\n@functions {\n    public async Task<IActionResult> OnGet()\n    {\n        if (SignInManager.IsSignedIn(User))\n        {\n            await SignInManager.SignOutAsync();\n        }\n\n        return LocalRedirect(Constants.Mappings.LOGIN_PATH);\n    }\n}"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Logout.cshtml.cs",
    "content": "using Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.RazorPages;\n\nnamespace Ticky.Web.Pages.Auth\n{\n    public class LogoutModel : PageModel\n    {\n        public void OnGet() { }\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/MailConfirmed.cshtml",
    "content": "@page\n@model MailConfirmedModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card justify-center items-center text-center\">\n        <i class=\"text-[16rem] fa-regular fa-circle-check text-primary\"></i>\n        <div class=\"flex flex-col\">\n            <h1 class=\"text-sm\">The e-mail address has been confirmed and the registration is successful.</h1>\n            <a href=\"~/\" class=\"auth-link !text-base\">Go to application</a>\n        </div>\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/MailConfirmed.cshtml.cs",
    "content": "namespace Ticky.Web.Pages.Auth;\n\npublic class MailConfirmedModel : PageModel\n{\n    public IActionResult OnGet()\n    {\n        return Page();\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/PasswordChanged.cshtml",
    "content": "@page\n@model PasswordChangedModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card justify-center items-center text-center\">\n        <i class=\"text-[16rem] fa-regular fa-circle-check text-primary\"></i>\n        <div class=\"flex flex-col\">\n            <h1 class=\"text-sm\">Your password was changed successfully. From now on, you may use the new password to log in.</h1>\n            <a href=\"~/\" class=\"auth-link !text-base\">Go to application</a>\n        </div>\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/PasswordChanged.cshtml.cs",
    "content": "namespace Ticky.Web.Pages.Auth;\n\npublic class PasswordChangedModel : PageModel\n{\n    public IActionResult OnGet()\n    {\n        return Page();\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Register.cshtml",
    "content": "﻿@page\n@model RegisterModel\n\n<main class=\"auth-bg\">\n    <section class=\"auth-card\">\n        <div class=\"flex flex-col gap-1\">\n            <h1 class=\"text-3xl font-extrabold\">Welcome!</h1>\n            @if (Constants.SMTP_ENABLED && !Constants.DISABLE_USER_SIGNUPS)\n            {\n                <label class=\"opacity-40\">Please provide some info for us to create an account for you</label>\n            }\n        </div>\n        @if(Constants.DISABLE_USER_SIGNUPS || !Constants.SMTP_ENABLED)\n        {\n            <div class=\"auth-form\">\n                @if(Constants.DISABLE_USER_SIGNUPS)\n                {\n                    <label class=\"auth-label\">User signups are currently disabled. Please contact the administrator if you need an account.</label>\n                } else {\n                    <label class=\"auth-label\">SMTP is not configured, please contact the administrator to create your account manually.</label>\n                }\n                <div class=\"flex flex-row items-center justify-center gap-1\">\n                    <div class=\"text-auth-bottom-text text-xs font-normal\">Already have an account?</div>\n                    <a class=\"auth-link\" href=\"/auth/login\">Log in</a>\n                </div>\n            </div>\n        }\n        else\n        {\n            @using (Html.BeginForm(FormMethod.Post, true, new { @class = \"auth-form\" }))\n            {\n                <div class=\"auth-inp-label\">\n                    @Html.LabelFor(model => model.Input.DisplayName, new { @class = \"auth-label\" })\n                    @Html.EditorFor(model => model.Input.DisplayName, new { htmlAttributes = new { @class = \"auth-input\" } })\n                    @Html.ValidationMessageFor(model => model.Input.DisplayName)\n                </div>\n                <div class=\"auth-inp-label\">\n                    @Html.LabelFor(model => model.Input.Email, new { @class = \"auth-label\" })\n                    @Html.EditorFor(model => model.Input.Email, new { htmlAttributes = new { @class = \"auth-input\" } })\n                    @Html.ValidationMessageFor(model => model.Input.Email)\n                </div>\n                <div class=\"auth-inp-label\">\n                    @Html.LabelFor(model => model.Input.Password, new { @class = \"auth-label\" })\n                    @Html.EditorFor(model => model.Input.Password, new { htmlAttributes = new { @class = \"auth-input\" } })\n                    @Html.ValidationMessageFor(model => model.Input.Password)\n                </div>\n                <div class=\"auth-inp-label\">\n                    @Html.LabelFor(model => model.Input.ConfirmPassword, new { @class = \"auth-label\" })\n                    @Html.EditorFor(model => model.Input.ConfirmPassword, new { htmlAttributes = new { @class = \"auth-input\" } })\n                    @Html.ValidationMessageFor(model => model.Input.ConfirmPassword)\n                </div>\n\n                @Html.AntiForgeryToken()\n\n                <button class=\"auth-button\" type=\"submit\">Create account</button>\n                <div class=\"flex flex-row items-center justify-center gap-1\">\n                    <div class=\"text-auth-bottom-text text-xs font-normal\">Already have an account?</div>\n                    <a class=\"auth-link\" href=\"/auth/login\">Log in</a>\n                </div>\n            }\n        }\n    </section>\n</main>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/Register.cshtml.cs",
    "content": "namespace Ticky.Web.Pages.Auth;\n\npublic class RegisterModel : PageModel\n{\n    private readonly UserManager<User> _userManager;\n    private readonly EmailService _emailService;\n    private readonly ILogger<RegisterModel> _logger;\n    private readonly CodeService _codeService;\n    private readonly AvatarService _avatarService;\n\n    [BindProperty]\n    public InputModel Input { get; set; } = new();\n\n    public RegisterModel(\n        UserManager<User> userManager,\n        EmailService emailService,\n        ILogger<RegisterModel> logger,\n        CodeService codeService,\n        AvatarService avatarService\n    )\n    {\n        _userManager = userManager;\n        _emailService = emailService;\n        _logger = logger;\n        _codeService = codeService;\n        _avatarService = avatarService;\n    }\n\n    public IActionResult OnGet()\n    {\n        return Page();\n    }\n\n    public async Task<IActionResult> OnPostAsync()\n    {\n        if (ModelState.IsValid)\n        {\n            var identity = new User\n            {\n                DisplayName = Input.DisplayName,\n                UserName = Input.Email,\n                Email = Input.Email,\n                ProfilePictureFileName = await _avatarService.FetchAvatarAsync(Input.DisplayName)\n            };\n\n            var result = await _userManager.CreateAsync(identity, Input.Password);\n\n            if (result.Succeeded)\n            {\n                var code = await _codeService.CreateCodeAsync(identity, CodePurpose.NewAccount);\n\n                try\n                {\n                    await _emailService.SendVerificationEmailAsync(Input.Email, code);\n                    return LocalRedirect($\"/auth/confirmmail?email={Input.Email}\");\n                }\n                catch (Exception ex)\n                {\n                    _logger.LogError(\n                        $\"Received an exception when sending an e-mail: {ex}. User received information about providing invalid e-mail.\"\n                    );\n                    ModelState.AddModelError(\n                        $\"{nameof(Input)}.{nameof(Input.Email)}\",\n                        \"The provided e-mail address does not exist.\"\n                    );\n\n                    await _userManager.DeleteAsync(identity);\n                }\n            }\n            else\n                foreach (var error in result.Errors)\n                {\n                    ModelState.AddModelError(\n                        $\"{nameof(Input)}.{nameof(Input.Password)}\",\n                        error.Description\n                    );\n                }\n        }\n\n        return Page();\n    }\n\n    public class InputModel\n    {\n        [Required(AllowEmptyStrings = false)]\n        [RegularExpression(\n            \"^[A-z1-9\\\\sá-žÁ-Ž-]*$\",\n            ErrorMessage = \"The name must not use any special characters.\"\n        )]\n        [Display(Name = \"Name to represent you\", Prompt = \"John Doe\")]\n        public string DisplayName { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        [EmailAddress]\n        [Display(Name = \"E-mail address\", Prompt = \"sample@email.com\")]\n        public string Email { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        [DataType(DataType.Password)]\n        [Display(Name = \"Password\", Prompt = \"●●●●●●●●●●●\")]\n        public string Password { get; set; } = string.Empty;\n\n        [Required(AllowEmptyStrings = false)]\n        [DataType(DataType.Password)]\n        [Display(Name = \"Repeat password\", Prompt = \"●●●●●●●●●●●\")]\n        [Compare(\"Password\", ErrorMessage = \"The passwords must match.\")]\n        public string ConfirmPassword { get; set; } = string.Empty;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/_AuthLayout.cshtml",
    "content": "@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\n\n<!DOCTYPE html>\n<html class=\"h-full w-full text-app-text\" lang=\"en\" data-theme=\"\">\n    <head>\n        <meta charset=\"utf-8\" />\n        <base href=\"~/\" />\n        <link rel=\"preload\" href=\"fonts/pxiGyp8kv8JHgFVrLPTucHtA.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLFj_Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLDz8Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiEyp8kv8JHgFVrJJfecg.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLDD4Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <link rel=\"preload\" href=\"fonts/pxiByp8kv8JHgFVrLBT5Z1xlFQ.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n        <link href=\"css/app.css\" rel=\"stylesheet\" />\n        <link rel=\"stylesheet\" href=\"fonts/Poppins.css\">\n        <link href=\"Ticky.Web.styles.css\" rel=\"stylesheet\" />\n        <link rel=\"icon\" type=\"image/png\" href=\"./images/favicon.ico\"/>\n        <link rel=\"stylesheet\" href=\"font-awesome/css/fontawesome.min.css\">\n        <link rel=\"stylesheet\" href=\"font-awesome/css/solid.min.css\">\n        <script src=\"js/main.js\"></script>\n        <title>Auth - @Constants.APP_NAME</title>\n    </head>\n    <body class=\"h-full w-full\">\n        @RenderBody()\n    </body>\n\n    <style>\n        body, input {\n            font-family: 'Poppins';\n            font-weight: 500;\n        }\n    </style>\n\n    <script src=\"js/darkTheme.js\" type=\"text/javascript\"></script>\n</html>"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/_ViewImports.cshtml",
    "content": "@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers"
  },
  {
    "path": "Ticky.Web/Components/Pages/Auth/_ViewStart.cshtml",
    "content": "@{\n    Layout = \"_AuthLayout.cshtml\";\n}"
  },
  {
    "path": "Ticky.Web/Components/Pages/BoardSettings.razor",
    "content": "@page \"/boards/settings/{Id:int}\"\n@using System.Reflection\n@using System.Text.Json\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject ILogger<BoardSettings> _logger\n@inject NavigationManager _navigationManager\n@inject IJSRuntime _js\n@inherits NotifiableBase\n\n<AddLabelModal @ref=\"_addLabelModal\" OnSubmit=\"() => RunNotification(typeof(Label), OperationType.Added)\" />\n<EditLabelModal @ref=\"_editLabelModal\" OnSubmit=\"() => RunNotification(typeof(Label), OperationType.Edited)\" />\n<EditCardModal @ref=\"_editCardModal\" OnSubmit=\"HandleUpdate\" />\n<DeleteConfirmationDialog T=\"Label\" @ref=\"_deleteLabelModal\" OnConfirmed=\"HandleUpdate\"/>\n<DeleteConfirmationDialog T=\"Card\" @ref=\"_deleteCardModal\" OnConfirmed=\"HandleUpdate\" />\n\n@if (_board is not null)\n{\n    <PageTitle>\n        Board settings - @_board.Name - @Constants.APP_NAME\n    </PageTitle>\n} else\n{\n    <PageTitle>\n        Board settings - @Constants.APP_NAME\n    </PageTitle>\n}\n\n<div class=\"w-full\">\n    <section class=\"flex w-full max-w-4xl flex-grow flex-col gap-5 overflow-y-auto px-12 py-14\">\n        <header class=\"flex flex-row justify-between text-2xl font-bold\">\n            <div class=\"flex flex-col gap-3\">\n                <a class=\"text-sm transition-colors link-muted hover:text-primary\" href=\"/boards/@Id\" title=\"Back to board\">\n                    <i class=\"fa fa-chevron-left mr-2\"></i>\n                    Back to board\n                </a>\n                <span>Board settings</span>\n            </div>\n        </header>\n\n        <section\n            class=\"flex w-full flex-row flex-wrap items-center justify-start gap-1 rounded-lg border border-tab-outline px-1 py-1 text-sm\">\n            <div data-active='@(_tab == 1 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"async () => await GoToTab(1)\">General</div>\n            <div data-active='@(_tab == 2 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"async () => await GoToTab(2)\">Labels</div>\n            <div data-active='@(_tab == 3 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"async () => await GoToTab(3)\">Snoozed cards</div>\n            <div data-active='@(_tab == 4 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"async () => await GoToTab(4)\">Repeating cards [BETA]</div>\n            <div data-active='@(_tab == 5 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"async () => await GoToTab(5)\">Export</div>\n        </section>\n\n        @if(_board is null)\n        {\n            <Spinner/>\n        } else {\n            <section class=\"flex w-full flex-col divide-y divide-tab-outline\">\n                @if(_tab == 1)\n                {\n                    <div class=\"flex flex-col py-5\">\n                        <label class=\"font-bold\">Board settings</label>\n                        <label class=\"text-sm opacity-70\">All the most important settings for this specific board, which do not belong to any other categories.</label>\n                    </div>\n                    <div class=\"settings-item\">\n                        <div class=\"flex flex-col text-sm\">\n                            <label class=\"font-bold opacity-90\">Disable sorting animations</label>\n                            <label class=\"w-4/5 max-w-2xl opacity-70\">With many cards in a column, animating their movement can cause lag. If you're experiencing this or prefer a quicker snap to position, enable this option.'</label>\n                        </div>\n\n                        <input type=\"checkbox\" class=\"switch\" checked=@_board.DisableSortingAnimations @onchange=\"(e) => OnSettingChanged(e, x => x.DisableSortingAnimations)\">\n                    </div>\n                } else if (_tab == 2)\n                {\n                    if(_labels is null)\n                    {\n                        <Spinner />\n                    } else {\n                        <div class=\"flex flex-col py-5\">\n                            <label class=\"font-bold\">Labels</label>\n                            <label class=\"text-sm opacity-70\">The settings for what labels are available for assignment to cards.</label>\n                        </div>\n\n                        <div class=\"flex flex-col gap-2 py-5\">\n                            @foreach (var label in _labels)\n                            {\n                                <div class=\"flex flex-row items-center\">\n                                    <LabelView Label=\"label\" />\n                                    <label class=\"ml-2 text-xs\">Used on @label.OnCards.Count cards</label>\n                                    <i class=\"fa fa-pencil edit-icon ml-2\" @onclick=\"() => _editLabelModal?.Open(_board, label)\" title=\"Edit label\"></i>\n                                    <i class=\"fa fa-trash-can edit-icon hover:text-red-button-hover\" @onclick=\"() => _deleteLabelModal!.OpenDialog(label)\" title=\"Delete label\"></i>\n                                </div>\n                            }\n                        </div>\n\n                        <button @onclick=\"() => _addLabelModal?.Open(_board)\">Create a label</button>\n                    }\n                } else if(_tab == 5)\n                {\n                    <div class=\"flex flex-col py-5\">\n                        <label class=\"font-bold\">Export</label>\n                        <label class=\"text-sm opacity-70\">Export the board to a JSON file, currently only for debugging purposes.</label>\n                    </div>\n                    <div class=\"flex flex-col gap-2 py-5\">\n                        <button disabled=@_isLoading class=\"btn btn-primary\" @onclick=\"ExportBoard\">\n                            @if(_isLoading) \n                            {\n                                <Spinner Small=true/>\n                            } else \n                            {\n                                <span>Export board</span>\n                            }\n                        </button>\n                    </div>\n\n                }\n                else if (_cards is null)\n                {\n                    <Spinner/>\n                } else if(_tab == 3)\n                {\n                    <div class=\"flex flex-col py-5\">\n                        <label class=\"font-bold\">Snoozed cards</label>\n                        <label class=\"text-sm opacity-70\">The list of cards that have been snoozed.</label>\n                    </div>\n\n                    <div class=\"flex flex-col gap-2 py-5\">\n                        @foreach(var snoozedCard in _cards)\n                        {\n                            <CardView Card=\"snoozedCard\" Column=\"_board.Columns.First(x => x.Id.Equals(snoozedCard.ColumnId))\" DeleteCardModal=\"_deleteCardModal\" EditCardModal=\"_editCardModal\" BoardCode=@_board.Code Members=\"_members\" OnCardUpdated=\"HandleUpdate\" Columns=\"_board.Columns\"/>\n                        }\n                    </div>\n                } else if(_tab == 4)\n                {\n                    <div class=\"flex flex-col py-5\">\n                        <label class=\"font-bold\">Repeat cards [BETA]</label>\n                        <label class=\"text-sm opacity-70\">The list of cards that are created on a repeating basis.</label>\n                    </div>\n\n                    <div class=\"flex flex-col gap-2 py-5\">\n                        @foreach(var repeatCard in _cards)\n                        {\n                            <CardView Card=\"repeatCard\" Column=\"_board.Columns.First(x => x.Id.Equals(repeatCard.ColumnId))\" DeleteCardModal=\"_deleteCardModal\" EditCardModal=\"_editCardModal\" BoardCode=@_board.Code Members=\"_members\" OnCardUpdated=\"HandleUpdate\" Columns=\"_board.Columns\" LongFormRepeat=true />\n                        }\n                    </div>\n                }\n            </section>\n        }\n    </section>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public int Id { get; set; } = default!;\n\n    private int _tab = 1;\n\n    private Board? _board;\n    private List<User> _members = [];\n    private List<Label>? _labels;\n    private List<Card>? _cards;\n    private AddLabelModal? _addLabelModal;\n    private EditLabelModal? _editLabelModal;\n    private EditCardModal? _editCardModal;\n    private DeleteConfirmationDialog<Label>? _deleteLabelModal;\n    private DeleteConfirmationDialog<Card>? _deleteCardModal;\n    private bool _isLoading;\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        await HandleUpdate();\n    }\n\n    private async Task LoadBoard()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .Include(x => x.Project)\n                .ThenInclude(x => x.Memberships)\n                    .ThenInclude(x => x.User)\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .Include(x => x.Columns)\n            .AsNoTracking()\n            .FirstOrDefaultAsync(x => x.Id.Equals(Id));\n\n        if (board is null || !board.VerifyAccess(_user))\n        {\n            MainLayout.RunNotification(new(\"This board either does not exist or you do not have access.\", NotificationType.Fail));\n            _navigationManager.NavigateTo(\"/\");\n            return;\n        }\n\n        _members = [];\n\n        if (board.Memberships.Any())\n            _members.AddRange(board.Memberships.Select(x => x.User));\n\n        if (board.Project.Memberships.Any())\n            _members.AddRange(board.Project.Memberships.Select(x => x.User));\n\n        _members = _members.DistinctBy(x => x.Id).ToList();\n\n        _members = [];\n\n        if (board.Memberships.Any())\n            _members.AddRange(board.Memberships.Select(x => x.User));\n\n        if (board.Project.Memberships.Any())\n            _members.AddRange(board.Project.Memberships.Select(x => x.User));\n\n        _members = _members.DistinctBy(x => x.Id).ToList();\n        _board = board;\n    }\n\n    protected override async Task HandleUpdate()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await LoadBoard();\n\n        if (_tab == 2)\n            _labels = await db.Labels\n                .Where(x => x.BoardId.Equals(Id))\n                .Include(x => x.OnCards)\n                .AsNoTracking()\n                .ToListAsync();\n        else if (_tab == 3)\n            _cards = await GetCardsBasedOnCondition(db, x => x.SnoozedUntil.HasValue);\n        else if (_tab == 4)\n            _cards = await GetCardsBasedOnCondition(db, x => x.RepeatInfo != null);\n\n        await base.HandleUpdate();\n    }\n\n    private async Task GoToTab(int tabNumber) \n    {\n        _tab = tabNumber;\n        await HandleUpdate();\n    }\n\n    private async Task<List<Card>> GetCardsBasedOnCondition(DataContext db, Expression<Func<Card, bool>> condition)\n        => await db.Boards\n            .Where(x => x.Id.Equals(Id))\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n            .SelectMany(x => x.Columns)\n            .SelectMany(x => x.Cards)\n            .Where(condition)\n            .Include(x => x.Labels)\n            .Include(x => x.CreatedBy)\n            .Include(x => x.Assignees)\n            .Include(x => x.Attachments)\n            .Include(x => x.Subtasks)\n            .Include(x => x.TimeRecords)\n            .AsNoTracking()\n            .ToListAsync();\n\n    private async void OnSettingChanged(ChangeEventArgs e, Expression<Func<Board, bool>> setter)\n    {\n        ArgumentNullException.ThrowIfNull(_board);\n\n        if (e.Value is not bool val)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards.FirstOrDefaultAsync(x => x.Id.Equals(_board.Id));\n\n        if (board is null)\n            return;\n\n        if (setter.Body is MemberExpression memberExpression && memberExpression.Member is PropertyInfo propertyInfo && propertyInfo.PropertyType == typeof(bool))\n            propertyInfo.SetValue(board, val);\n        else throw new Exception(\"Invalid property provided.\");\n\n        await db.SaveChangesAsync();\n\n        await RunNotification(typeof(BoardSettings), OperationType.Edited);\n    }\n\n    private async Task ExportBoard()\n    {\n        _isLoading = true;\n        StateHasChanged();\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .AsNoTracking()\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Labels)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.TimeRecords)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Reminders)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Comments)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Activities)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Assignees)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Attachments)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.LinkedIssuesOne)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.LinkedIssuesTwo)\n            .Include(x => x.Columns)\n                .ThenInclude(x => x.Cards)\n                    .ThenInclude(x => x.Subtasks)\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .Include(x => x.Labels)\n            .Include(x => x.Project)\n                .ThenInclude(x => x.Memberships)\n            .FirstAsync(x => x.Id.Equals(Id));\n\n        await _js.InvokeVoidAsync(\"downloadJsonText\", $\"{board.Name}_{board.CreatedAt.Ticks}.json\", JsonSerializer.Serialize(board, new JsonSerializerOptions\n        {\n            ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles\n        }));\n\n        _isLoading = false;\n        StateHasChanged();\n        MainLayout.RunNotification(new(\"Board exported successfully.\"));\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/BoardView.razor",
    "content": "@page \"/boards/{Id:int}/{CardId:int?}\"\n@using System.Security.Cryptography\n@using System.IO\n@inject NavigationManager _navigationManager\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject ProtectedLocalStorage _protectedLocalStorage\n@inject IJSRuntime _js\n@inject ILogger<BoardView> _logger\n@inject IHttpContextAccessor _httpContextAccessor\n@inherits NotifiableBase\n\n@if (_board is not null)\n{\n    <PageTitle>\n        @_board.Name - @Constants.APP_NAME\n    </PageTitle>\n}\n\n<CreateColumnModal @ref=\"_createColumnModal\" OnSubmit=\"async () => await RunNotification(typeof(Column), OperationType.Added)\" />\n<EditColumnModal @ref=\"_editColumnModal\" OnSubmit=\"async () => await RunNotification(typeof(Column), OperationType.Edited)\" />\n<DeleteConfirmationDialog T=\"Column\" @ref=\"_deleteColumnModal\" OnConfirmed=\"HandleUpdate\" />\n<DeleteConfirmationDialog T=\"Card\" @ref=\"_deleteTaskModal\" OnConfirmed=\"HandleUpdate\" />\n<EditCardModal @ref=\"_editCardModal\" OnSubmit=\"OnTaskEdited\" />\n<EditBoardMembershipsModal @ref=\"_editBoardMembershipsModal\" OnSubmit=\"async () => await RunNotification(typeof(BoardMembership), OperationType.Edited)\" />\n<FilterCardsModal @ref=\"_filterCardsModal\" Model=\"_filterModel\" SearchUpdated=\"LoadCardsAsync\" BoardMembers=\"_members\" BoardLabels=\"_labels\" />\n\n<div class=\"flex w-screen flex-col divide-y divide-tab-outline\">\n    <header id=\"board-header\" class=\"flex flex-row items-center justify-end gap-1 px-2 py-2 text-2xl font-bold sm:gap-5 sm:px-12\">\n        @if(_board is null)\n        {\n            <Spinner/>\n        } else {\n            <label class=\"mr-auto text-sm text-ellipsis md:text-xl\">@_board.Name <label class=\"text-2xs font-normal text-ellipsis\">(Project @_board.Project.Name)</label></label>\n\n            <div class=\"hidden flex-row gap-1 2xs:flex\">\n                @{\n                    var i = 0;\n                }\n                @foreach(var member in _members)\n                {\n                    string id = $\"avatar_{i}\";\n                    <div id=\"@id\" class=\"avatar stack-avatars\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@member.ProfilePictureFileName');\" @onclick=\"() => MainLayout.UserInfoModal?.Open(id, member.Id)\"></div>\n                    i++;\n                }\n                @if (IsAdmin())\n                {\n                    <div class=\"avatar add\" @onclick=\"() => _editBoardMembershipsModal?.Open(_board.Id, _board.ProjectId)\" title=\"Add member\">\n                        <i class=\"fa fa-plus text-sm\"></i>\n                    </div>\n                }\n            </div>\n\n            @if (IsAdmin())\n            {\n                <a href=\"/boards/settings/@_board.Id\"><i class=\"fa fa-gear icon-button\" title=\"Board settings\"></i></a>\n            }\n\n            var filterIcon = \"filter-icon\";\n            <span class=\"relative inline-block\">\n                <i id=@filterIcon class=\"fa fa-filter icon-button @( _filterModel.IsAnyFilterApplied() ? \"text-primary hover:text-primary-hover\" : string.Empty)\" title=\"Filter cards\" @onclick=\"() => _filterCardsModal?.Open(filterIcon)\"></i>\n                @if (_filterModel.IsAnyFilterApplied())\n                {\n                    <span class=\"absolute top-0 right-0 h-2 w-2 rounded-full border-2 border-white bg-primary hover:bg-primary-hover\"></span>\n                }\n            </span>\n            <i class=\"fa fa-chart-simple icon-button\" @onclick=\"SwitchStatsDisplay\" title=\"Toggle statistics\"></i>\n        }\n    </header>\n    <section class='h-board-content flex w-screen flex-row divide-x divide-tab-outline'>\n        <!-- Board section -->\n        @if (_board is not null)\n        {\n            <section id=\"board-section\" class=\"w-full flex-row gap-5 overflow-x-auto @(_preferences.ShowStats ? \"hidden md:flex\" : \"flex\") py-6\">\n                <SortableList Class=\"ml-12 flex flex-row gap-5\" Animation=@(_board.DisableSortingAnimations ? 0 : 200) Items=\"_board.Columns.OrderBy(x => x.Index).ToList()\" Context=\"column\" OnUpdate=\"OnColumnMoved\" Direction=\"horizontal\" Handle=\".drag-toggle\" Pull=false Put=false>\n                    <SortableItemTemplate>\n                        <ColumnView @key=\"column.Id\" Column=\"column\" Cards=\"_cards\" Members=\"_members\" Board=\"@_board\" EditColumnModal=\"_editColumnModal\" DeleteColumnModal=\"_deleteColumnModal\" EditCardModal=\"_editCardModal\" DeleteCardModal=\"_deleteTaskModal\" OnCardMoved=StateHasChanged AddingSetter=SetAdding IsAdmin=\"IsAdmin\" AddingCardHere=\"(_adding == column.Id)\" OnUpdate=\"HandleUpdate\" />\n                    </SortableItemTemplate>\n                </SortableList>\n\n                @if (IsAdmin())\n                {\n                    <div class=\"add max-h-visible-screen mt-1 mr-12 min-w-64 rounded-lg px-8\" @onclick=\"() => _createColumnModal?.Open(_board.Id)\" style=\"order: @(_board.Columns.Any() ? _board.Columns.Max(x => x.Id)+1 : 0);\">\n                        <i class=\"fa fa-plus text-3xl\" title=\"Add new column\"></i>\n                        <label>New column</label>\n                    </div>\n                }\n            </section>\n            \n            if(_preferences.ShowStats) \n            {\n                <section class=\"flex w-screen flex-col items-center gap-6 px-2 py-6 md:w-80\">\n                    <div class=\"flex w-full flex-row items-center justify-between\">\n                        <h1>Progress</h1>\n                        <i class=\"fa fa-xmark icon-button\" @onclick=SwitchStatsDisplay title=\"Close statistics\"></i>\n                    </div>\n                    <div class=\"flex w-full flex-col gap-8\">\n                        <!-- Side section -->\n                        @if (_board is not null)\n                        {\n                            var completedCards = _cards.Count(x => x.Column.Finished);\n                            var totalCards = _cards.Count();\n\n                            <div class=\"flex flex-col gap-4\">\n                                <div class=\"flex flex-col gap-1\">\n                                    <div class=\"flex flex-row justify-between text-xs\">\n                                        <label>Tasks completed</label>\n                                        <label class=\"text-gray-500\">@completedCards/@totalCards</label>\n                                    </div>\n                                    <div class=\"grid h-1 w-full rounded-lg\">\n                                        <div class=\"z-10 w-24 rounded-lg bg-pink-500 transition-all\" style=\"grid-row: 1; grid-column: 1; width: @(totalCards == 0 ? 0 : Math.Round((double) completedCards/totalCards*100))%;\"></div>\n                                        <div class=\"rounded-lg bg-pink-300\" style=\"grid-row: 1; grid-column: 1;\"></div>\n                                    </div>\n                                </div>\n\n                                <!-- Column time totals -->\n                                <div class=\"flex flex-col gap-2\">\n                                    <h2 class=\"text-sm\">Column time totals</h2>\n                                    @foreach(var col in _board.Columns.OrderBy(c => c.Index))\n                                    {\n                                        var colCards = _cards.Where(c => c.ColumnId == col.Id).ToList();\n                                        var colTotal = colCards.Select(x => x.GetTotalTime()).Sum();\n                                        var perUser = colCards.SelectMany(x => x.TimeRecords).GroupBy(x => x.UserId).Select(x => new KeyValuePair<int,TimeSpan>(x.Key, x.Select(y => y.GetTotalTime()).Sum())).ToDictionary(x => x.Key, x => x.Value);\n                                        var expandId = $\"columnTime_{col.Id}\";\n\n                                        <div class=\"rounded-lg border border-tab-outline p-2\">\n                                            <div class=\"flex flex-row items-center justify-between\">\n                                                <div class=\"flex items-center gap-2\">\n                                                    <label class=\"text-sm font-semibold\">@col.Name</label>\n                                                    <label class=\"text-2xs text-gray-500\">@colTotal.ToElapsedString()</label>\n                                                </div>\n                                                <div>\n                                                    <button class=\"text-xs text-primary px-3 py-1 rounded\" @onclick=\"() => ToggleExpand(expandId)\">@(IsExpanded(expandId) ? \"Hide\" : \"Show\")</button>\n                                                </div>\n                                            </div>\n\n                                            @if (IsExpanded(expandId))\n                                            {\n                                                <div class=\"mt-2 ml-2 text-xs\">\n                                                    @if (perUser.Any())\n                                                    {\n                                                        @foreach(var kv in perUser.OrderByDescending(k => k.Value))\n                                                        {\n                                                            var user = _members.FirstOrDefault(m => m.Id == kv.Key);\n                                                            <div class=\"flex flex-row justify-between\">\n                                                                <div class=\"text-ellipsis\">@(user != null ? user.Name : \"Unknown\")</div>\n                                                                <div class=\"text-gray-500\">@kv.Value.ToElapsedString()</div>\n                                                            </div>\n                                                        }\n                                                    }\n                                                    else\n                                                    {\n                                                        <div class=\"text-gray-500\">No time tracked</div>\n                                                    }\n                                                </div>\n                                            }\n                                        </div>\n                                    }\n                                </div>\n                            </div>\n                        }\n                        else\n                        {\n                            <Spinner />\n                        }\n                    </div>\n                </section>\n            }\n        }\n        else\n        {\n            <Spinner />\n        }\n    </section>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [Parameter]\n    public int Id { get; set; } = default!;\n\n    [Parameter]\n    public int? CardId { get; set; }\n\n    private string FILTERS_SCOPED_KEY { get => $\"{Constants.StorageKeys.FilterPreferencesPrefix}_{Id}\"; }\n\n    private Board? _board;\n    private List<User> _members = [];\n    private List<Card> _cards = [];\n    private List<Label> _labels = [];\n    private Guid _pageId = Guid.NewGuid();\n\n    private CreateColumnModal? _createColumnModal;\n    private EditColumnModal? _editColumnModal;\n    private EditCardModal? _editCardModal;\n    private DeleteConfirmationDialog<Column>? _deleteColumnModal;\n    private DeleteConfirmationDialog<Card>? _deleteTaskModal;\n    private EditBoardMembershipsModal? _editBoardMembershipsModal;\n    private FilterCardsModal? _filterCardsModal;\n    private List<ElementReference> _avatars = [];\n    private ElementReference Avatars { set => _avatars.Add(value); }\n\n    private int _adding;\n    private BoardPreferencesModel _preferences = new();\n    private FilterCardsModel _filterModel = new();\n    private int? _initialCardId;\n\n    private HubConnection? _hubConnection;\n    private HashSet<string> _expandedSections = new();\n\n    protected override void OnParametersSet()\n    {\n        if (_board is null || !CardId.HasValue || _initialCardId == CardId)\n            return;\n\n        _initialCardId = CardId;\n        _editCardModal?.Open(CardId.Value, _members, _board.Columns);\n    }\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        var httpContext = _httpContextAccessor.HttpContext;\n        var uri = new Uri(\"http://localhost:8080\" + Constants.Hubs.UPDATE_HUB);\n\n#if DEBUG\n        uri = new Uri(\"https://localhost:7225\" + Constants.Hubs.UPDATE_HUB);\n#endif\n\n        _hubConnection = new HubConnectionBuilder()\n            .WithUrl(uri, options =>\n            {\n\t\t\t\tvar cookieName = \".AspNetCore.Identity.Application\";\n                var cookieValue = httpContext?.Request?.Cookies[cookieName];\n\n                if (!string.IsNullOrEmpty(cookieValue))\n                {\n                    options.Cookies.Add(new System.Net.Cookie\n                    {\n                        Name = cookieName,\n                        Value = cookieValue,\n                        Domain = uri.Host\n                    });\n                }\n            })\n            .WithAutomaticReconnect()\n            .Build();\n\n        _hubConnection.On<int, Guid>(nameof(UpdateHub.BoardChange), async (boardId, pageId) =>\n        {\n            if (boardId != Id || pageId == _pageId)\n                return;\n\n            await HandleRemoteUpdate();\n        });\n\n        _ = HandleConnectionAsync();\n\n        _initialCardId = CardId;\n\n        try\n        {\n            var boardPreferences = await _protectedLocalStorage.GetAsync<BoardPreferencesModel>(Constants.StorageKeys.BoardPreferences);\n            _preferences = (boardPreferences.Success ? boardPreferences.Value : new()) ?? new();\n        }\n        catch (CryptographicException)\n        {\n            _preferences = new();\n        }\n\n        try\n        {\n            var filterPreferences = await _protectedLocalStorage.GetAsync<FilterCardsModel>(FILTERS_SCOPED_KEY);\n            _filterModel = (filterPreferences.Success ? filterPreferences.Value : new()) ?? new();\n        }\n        catch(CryptographicException)\n        {\n            _filterModel = new();\n        }\n\n        await HandleUpdate();\n\n        if (_board is null)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var user = await db.Users\n            .Include(x => x.LastVisits)\n            .FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if (user is null)\n            return;\n\n        user.LastVisitedBoardId = _board.Id;\n\n        var pastVisit = user.LastVisits.FirstOrDefault(x => x.BoardId.Equals(_board.Id));\n\n        if (pastVisit is not null)\n            user.LastVisits.Remove(pastVisit);\n\n        user.LastVisits.Add(new LastVisit\n        {\n            UserId = _user.Id,\n            BoardId = _board.Id,\n            VisitTime = DateTime.Now\n        });\n\n        await db.SaveChangesAsync();\n\n        if(CardId.HasValue)\n            _editCardModal?.Open(CardId.Value, _members, _board.Columns);\n\n        await MainLayout.UpdateRecentBoard();\n    }\n\n    private async Task HandleConnectionAsync()\n    {\n        if(_hubConnection is null)\n            return;\n\n        try\n        {\n            await _hubConnection.StartAsync();\n            await _hubConnection.SendAsync(nameof(UpdateHub.SubscribeBoard), Id);\n        } catch(Exception ex)\n        {\n            _logger.LogError(ex, \"Failed to start hub connection or subscribe to board {BoardId}\", Id);\n            MainLayout.RunNotification(new(\"Real-time updates unavailable. Please refresh the page.\", NotificationType.Fail));\n        }\n    }\n\n    private async Task SwitchStatsDisplay()\n    {\n        _preferences.ShowStats = !_preferences.ShowStats;\n\n        try\n        {\n            await _protectedLocalStorage.SetAsync(Constants.StorageKeys.BoardPreferences, _preferences);\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(ex, \"Failed to save board preferences.\");\n        }\n\n        StateHasChanged();\n    }\n\n    private async Task OnColumnMoved((string movedItemId, string? targetItemId, string _) args)\n    {\n        if(_board is null)\n            return;\n\n        var movedColumnId = Convert.ToInt32(args.movedItemId);\n        var snapshot = _board.Columns.Select(c => new { c.Id, c.Index }).ToList();\n\n        var movedColumn = _board.Columns.FirstOrDefault(x => x.Id.Equals(movedColumnId));\n\n        if (movedColumn is null)\n            return;\n\n        int targetIndex = _board.Columns.Any() ? _board.Columns.Max(x => x.Index) + 1 : 0;\n        int? targetItemId = args.targetItemId is not null ? Convert.ToInt32(args.targetItemId) : null;\n\n        if (targetItemId.HasValue)\n        {\n            var targetColumn = _board.Columns.FirstOrDefault(x => x.Id.Equals(targetItemId));\n            if (targetColumn is not null)\n            {\n                targetIndex = targetColumn.Index;\n                foreach (var column in _board.Columns.OrderByDescending(x => x.Index))\n                {\n                    if (column.Index >= targetColumn.Index)\n                        column.Index++;\n                }\n            }\n        }\n\n        movedColumn.Index = targetIndex;\n        IndexHelper.FixIndices(_board.Columns);\n        StateHasChanged();\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var targetBoard = db.Boards\n                .Include(x => x.Columns)\n                .FirstOrDefault(x => x.Id.Equals(Id));\n\n            if (targetBoard is null)\n                throw new InvalidOperationException(\"Board not found in DB.\");\n\n            var dbMovedColumn = targetBoard.Columns.FirstOrDefault(x => x.Id.Equals(movedColumnId));\n            if (dbMovedColumn is null)\n                throw new InvalidOperationException(\"Moved column not found in DB.\");\n\n            int dbTargetIndex = targetBoard.Columns.Any() ? targetBoard.Columns.Max(x => x.Index) + 1 : 0;\n            if (targetItemId.HasValue)\n            {\n                var dbTargetColumn = targetBoard.Columns.FirstOrDefault(x => x.Id.Equals(targetItemId));\n                if (dbTargetColumn is not null)\n                {\n                    dbTargetIndex = dbTargetColumn.Index;\n                    foreach (var column in targetBoard.Columns.OrderByDescending(x => x.Index))\n                    {\n                        if (column.Index >= dbTargetColumn.Index)\n                            column.Index++;\n                    }\n                }\n            }\n\n            dbMovedColumn.Index = dbTargetIndex;\n            IndexHelper.FixIndices(targetBoard.Columns);\n\n            await db.SaveChangesAsync();\n            await HandleUpdate();\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(ex, \"Failed to persist moved column.\");\n\n            foreach (var oldColumnPosition in snapshot)\n            {\n                var column = _board.Columns.FirstOrDefault(x => x.Id == oldColumnPosition.Id);\n                if (column is not null)\n                    column.Index = oldColumnPosition.Index;\n            }\n\n            IndexHelper.FixIndices(_board.Columns);\n            StateHasChanged();\n\n            MainLayout.RunNotification(new(\"Failed to move column. Changes were reverted.\", NotificationType.Fail));\n        }\n    }\n\n    private async Task OnDataChanged()\n    {\n        if(_hubConnection is null || _hubConnection.State != HubConnectionState.Connected)\n            return;\n\n        await _hubConnection.SendAsync(nameof(UpdateHub.BoardChange), Id, _pageId);\n    }\n\n    private async Task HandleRemoteUpdate()\n    {\n        await LoadBoardAsync();\n    }\n\n    protected override async Task HandleUpdate()\n    {\n        await LoadBoardAsync();\n        await OnDataChanged();\n    }\n\n    private async Task LoadBoardAsync()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var board = await db.Boards\n            .Include(x => x.Columns)\n            .Include(x => x.Labels)\n            .Include(x => x.Project)\n                .ThenInclude(x => x.Memberships)\n                    .ThenInclude(x => x.User)\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .AsNoTracking()\n            .FirstOrDefaultAsync(x => x.Id.Equals(Id));\n\n        if(board is null || !board.VerifyAccess(_user))\n        {\n            MainLayout.RunNotification(new(\"This board either does not exist or you do not have access.\", NotificationType.Fail));\n            _navigationManager.NavigateTo(\"/\");\n            return;\n        }\n\n        _members = [];\n\n        if (board.Memberships.Any())\n            _members.AddRange(board.Memberships.Select(x => x.User));\n\n        if (board.Project.Memberships.Any())\n            _members.AddRange(board.Project.Memberships.Select(x => x.User));\n\n        _members = _members.DistinctBy(x => x.Id).ToList();\n        _labels = board.Labels;\n        _board = board;\n\n        await LoadCardsAsync();\n\n        await InvokeAsync(StateHasChanged);\n    }\n\n    private async Task LoadCardsAsync()\n    {\n        ArgumentNullException.ThrowIfNull(_board);\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var columnIds = _board.Columns.Select(x => x.Id).ToList();\n\n        var queryableCards = db.Cards\n            .AsNoTracking()\n            .Include(x => x.CreatedBy)\n            .Include(x => x.Assignees)\n            .Include(x => x.Attachments)\n            .Include(x => x.Subtasks)\n            .Include(x => x.Labels)\n            .Include(x => x.TimeRecords)\n            .Include(x => x.Column)\n            .Where(x => columnIds.Contains(x.ColumnId))\n            .Where(x => !x.SnoozedUntil.HasValue);\n\n        if (_filterModel.ExcludeCompleted)\n            queryableCards = queryableCards.Where(x => !x.Column.Finished);\n\n        if(!string.IsNullOrWhiteSpace(_filterModel.Text))\n        {\n            var query = _filterModel.Text.Trim();\n            queryableCards = queryableCards.Where(x => x.Name.Contains(query) || (x.Column.Board.Code + \"-\" + x.Number).Contains(query) || (x.Description != null && x.Description.Contains(query)));\n        }\n\n        if (_filterModel.AssignedUserIds.Count > 0 || _filterModel.IncludeUnassigned)\n            queryableCards = queryableCards.Where(card =>\n                (_filterModel.AssignedUserIds.Count > 0 && card.Assignees.Any(a => _filterModel.AssignedUserIds.Contains(a.Id)))\n                || (_filterModel.IncludeUnassigned && !card.Assignees.Any())\n            );\n\n        if (_filterModel.LabelIds.Count > 0)\n            queryableCards = queryableCards.Where(card => card.Labels.Any(x => _filterModel.LabelIds.Contains(x.Id)));\n\n        _cards = await queryableCards.ToListAsync();\n\n        await InvokeAsync(StateHasChanged);\n\n        try\n        {\n            await _protectedLocalStorage.SetAsync(FILTERS_SCOPED_KEY, _filterModel);\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(ex, \"Failed to save filter preferences.\");\n        }\n    }\n\n    private bool IsAdmin()\n    {\n        if(_board is null)\n            return false;\n\n        var boardMembership = _board.Memberships.FirstOrDefault(x => x.UserId.Equals(_user.Id));\n\n        if(boardMembership is null)\n        {\n            var projectMembership = _board.Project.Memberships.FirstOrDefault(x => x.UserId.Equals(_user.Id));\n\n            if(projectMembership is null)\n                return false;\n\n            return projectMembership.IsAdmin;\n        }\n\n        return boardMembership.IsAdmin;\n    }\n\n    private async Task OnTaskEdited()\n    {\n        ArgumentNullException.ThrowIfNull(_board);\n\n        await HandleUpdate();\n    }\n\n    private void SetAdding(int columnId)\n    {\n        _adding = columnId;\n    }\n\n    private void ToggleExpand(string id)\n    {\n        if (_expandedSections.Contains(id))\n            _expandedSections.Remove(id);\n        else\n            _expandedSections.Add(id);\n\n        StateHasChanged();\n    }\n\n    private bool IsExpanded(string id) => _expandedSections.Contains(id);\n}\n\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Error.razor",
    "content": "﻿@page \"/Error\"\n@using System.Diagnostics\n\n<PageTitle>Error</PageTitle>\n\n<h1 class=\"text-danger\">Error.</h1>\n<h2 class=\"text-danger\">An error occurred while processing your request.</h2>\n\n@if (ShowRequestId)\n{\n    <p>\n        <strong>Request ID:</strong> <code>@RequestId</code>\n    </p>\n}\n\n<h3>Development Mode</h3>\n<p>\n    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.\n</p>\n<p>\n    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>\n    It can result in displaying sensitive information from exceptions to end users.\n    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>\n    and restarting the app.\n</p>\n\n@code{\n    [CascadingParameter]\n    private HttpContext? HttpContext { get; set; }\n\n    private string? RequestId { get; set; }\n    private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);\n\n    protected override void OnInitialized() =>\n        RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/Home.razor",
    "content": "@page \"/\"\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inherits NotifiableBase\n\n<CreateProjectModal @ref=\"_createProjectModal\" OnSubmit=\"async () => await RunNotification(typeof(Project), OperationType.Added)\" />\n<ImportModal @ref=\"_importModal\" OnSubmit=\"HandleUpdate\" />\n<CreateBoardModal @ref=\"_createBoardModal\" OnSubmit=\"async () => await RunNotification(typeof(Board), OperationType.Added)\" ImportModal=\"_importModal\" />\n<EditProjectModal @ref=\"_editProjectModal\" OnSubmit=\"async () => await RunNotification(typeof(Project), OperationType.Edited)\" />\n<EditProjectMembershipsModal @ref=\"_editProjectMembershipsModal\" OnSubmit=\"async () => await RunNotification(typeof(ProjectMembership), OperationType.Edited)\" />\n<DeleteConfirmationDialog T=\"Project\" @ref=\"_deleteProjectModal\" OnConfirmed=\"HandleUpdate\" />\n<DeleteConfirmationDialog T=\"Board\" @ref=\"_deleteBoardModal\" OnConfirmed=\"HandleUpdate\" />\n\n<PageTitle>Home - @Constants.APP_NAME</PageTitle>\n\n<div class=\"flex w-full flex-col gap-10 overflow-y-auto px-12 py-14\">\n    <div class=\"flex flex-row items-center justify-end gap-5\">\n        <div class=\"mr-auto flex flex-col gap-2\">\n            <header class=\"text-2xl font-bold\">\n                Hey there\n            </header>\n            <label class=\"opacity-60\">On this home page you can create a new board/project or open an existing one.</label>\n        </div>\n        <button class=\"flex flex-row items-center justify-between gap-2 px-10 py-2 shadow-lg\" @onclick=\"() => _createProjectModal?.Open()\"><i class=\"fa fa-plus\" title=\"Create new project\"></i>New project</button>\n    </div>\n\n    @if (_projects is not null && _remainingBoards is not null)\n    {\n        foreach (var project in _projects)\n        {\n            <section class=\"flex flex-col gap-2\">\n                <div class=\"flex flex-row justify-between\">\n                    <div class=\"flex flex-row items-center gap-2\">\n                        <label>Project @project.Name</label>\n                        @if(project.Memberships.First(x => x.UserId.Equals(_user.Id)).IsAdmin) \n                        {\n                            <Dropdown Actions='new() {\n                                { \"Edit project\", () => _editProjectModal?.Open(project.Id)},\n                                { \"Delete project\", () => _deleteProjectModal?.OpenDialog(project) }\n                            }'>\n                                <i class=\"fa fa-ellipsis icon-button\" title=\"Project options\"></i>\n                            </Dropdown>\n                        }\n                    </div>\n\n                    <div class=\"flex flex-row gap-1\">\n                        @{\n                            var i = 0;\n                        }\n                        @foreach(var member in project.Memberships.OrderBy(x => x.AddedAt))\n                        {\n                            string id = $\"avatar_{i}\";\n                            <div id=\"@id\" class=\"avatar stack-avatars\" style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@member.User.ProfilePictureFileName');\"\n                            @onclick=\"() => _mainLayout.UserInfoModal?.Open(id, member.UserId)\"></div>\n                        }\n                        @if (project.Memberships.First(x => x.UserId.Equals(_user.Id)).IsAdmin)\n                        {\n                            <div class=\"avatar add\" @onclick=\"() => _editProjectMembershipsModal?.Open(project.Id)\" title=\"Add member\">\n                                <i class=\"fa fa-plus text-sm\"></i>\n                            </div>\n                        }\n                    </div>\n                </div>\n                <div class=\"flex w-full flex-row flex-wrap gap-5\">\n                    @foreach (var board in project.Boards.OrderByDescending(x => x.Favorites.Any(y => y.BoardId.Equals(x.Id))).ThenByDescending(x => x.LastVisits.Select(y => y.VisitTime).OrderByDescending(y => y).FirstOrDefault()))\n                    {\n                        <BoardCard Board=\"board\" IsAdmin=\"board.Memberships.Any(x => x.UserId.Equals(_user.Id) && x.IsAdmin) || project.Memberships.Any(x => x.UserId.Equals(_user.Id) && x.IsAdmin)\" OnEdit=\"async () => await RunNotification(typeof(Board), OperationType.Edited)\" OnFavorite=\"async () => await RunNotification(typeof(Board), OperationType.Favorited)\" DeleteConfirmationDialog=\"_deleteBoardModal\" />\n                    }\n                    @if(project.Memberships.First(x => x.UserId.Equals(_user.Id)).IsAdmin) \n                    {\n                        <div class=\"board-card-create\" @onclick=\"() => _createBoardModal?.Open(project.Id)\" title=\"Create new board\">\n                            <i class=\"fa fa-plus text-3xl\"></i>\n                            New board\n                        </div>\n                    }\n                </div>\n            </section>\n        }\n\n        @if (_remainingBoards.Any())\n        {\n            <section class=\"flex flex-col gap-2\">\n                <div class=\"flex flex-row justify-between\">\n                    <div class=\"flex flex-row items-center gap-2\">\n                        <label>Uncategorized boards</label>\n                    </div>\n                </div>\n                <div class=\"flex w-full flex-row flex-wrap gap-5\">\n                    @foreach (var board in _remainingBoards.OrderByDescending(x => x.Favorites.Any(y => y.BoardId.Equals(x.Id))).ThenByDescending(x => x.LastVisits.Select(y => y.VisitTime).OrderByDescending(y => y).FirstOrDefault()))\n                    {\n                        <BoardCard Board=\"board\" IsAdmin=\"board.Memberships.First(x => x.UserId.Equals(_user.Id)).IsAdmin\" OnEdit=\"async () => await RunNotification(typeof(Board), OperationType.Edited)\" OnFavorite=\"async () => await RunNotification(typeof(Board), OperationType.Favorited)\" DeleteConfirmationDialog=\"_deleteBoardModal\" />\n                    }\n                </div>\n            </section>\n        }\n    }\n    else\n    {\n        <Spinner />\n    }\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User _user { get; set; } = default!;\n\n    [CascadingParameter(Name = Constants.CascadingParameters.MainLayout)]\n    private MainLayout _mainLayout { get; set; } = default!;\n\n    private IEnumerable<Project>? _projects;\n\n    private IEnumerable<Board>? _remainingBoards;\n\n    private CreateProjectModal? _createProjectModal;\n\n    private CreateBoardModal? _createBoardModal;\n\n    private EditProjectModal? _editProjectModal;\n\n    private EditProjectMembershipsModal? _editProjectMembershipsModal;\n\n    private DeleteConfirmationDialog<Project>? _deleteProjectModal;\n\n    private DeleteConfirmationDialog<Board>? _deleteBoardModal;\n\n    private ImportModal? _importModal;\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender)\n            return;\n\n        await HandleUpdate();\n        StateHasChanged();\n    }\n\n    protected override async Task HandleUpdate() \n    {\n        _projects = await LoadProjectsAsync();\n        _remainingBoards = await LoadRemainingBoardsAsync();\n    }\n\n    private async Task<IEnumerable<Project>> LoadProjectsAsync()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var projects = await db.Projects\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .Where(x => x.Memberships.Any(membership => membership.UserId.Equals(_user.Id)))\n            .Include(x => x.Boards)\n                .ThenInclude(x => x.Memberships)\n                    .ThenInclude(x => x.User)\n            .Include(x => x.Boards)\n                .ThenInclude(x => x.Columns)\n                    .ThenInclude(x => x.Cards)\n                        .ThenInclude(x => x.TimeRecords)\n            .Include(x => x.Boards)\n                .ThenInclude(x => x.LastVisits)\n                    .ThenInclude(x => x.User)\n            .Include(x => x.Boards)\n                .ThenInclude(x => x.Favorites)\n            .AsNoTracking()\n            .ToListAsync();\n\n        return projects;\n    }\n\n    private async Task<IEnumerable<Board>> LoadRemainingBoardsAsync()\n    {\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var boards = await db.Boards\n            .Include(x => x.Memberships)\n                .ThenInclude(x => x.User)\n            .Include(x => x.Project)\n                .ThenInclude(x => x.Memberships)\n                    .ThenInclude(x => x.User)\n            .Include(x => x.Favorites)\n            .Where(x => x.Memberships.Any(membership => membership.UserId.Equals(_user.Id)))\n            .Include(x => x.Columns)\n                    .ThenInclude(x => x.Cards)\n                        .ThenInclude(x => x.TimeRecords)\n            .Include(x => x.LastVisits)\n                .ThenInclude(x => x.User)\n            .AsNoTracking()\n            .ToListAsync();\n\n        if(_projects is not null)\n            boards = boards.Where(x => !_projects.Any(project => project.Id.Equals(x.ProjectId))).ToList();\n\n        return boards;\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Pages/UserSettings.razor",
    "content": "@page \"/settings/{Tab:int?}\"\n@using System.Reflection\n@inject IDbContextFactory<DataContext> _dbContextFactory\n@inject ILogger<UserSettings> _logger\n@inject AvatarService _avatarService\n@inject UserManager<User> _userManager\n@inject NavigationManager _navigationManager\n@inherits NotifiableBase\n@implements IDisposable\n\n<PageTitle>Settings - @Constants.APP_NAME</PageTitle>\n\n<div class=\"w-full\">\n    <section class=\"flex w-full max-w-4xl grow flex-col gap-5 overflow-y-auto px-12 py-14\">\n        <header class=\"flex flex-row justify-between text-2xl font-bold\">\n            User settings\n        </header>\n\n        <section\n            class=\"flex w-full flex-row flex-wrap items-center justify-start gap-1 rounded-lg border border-tab-outline px-1 py-1 text-sm\">\n            <div data-active='@(_tab == 1 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"() => GoToTab(1)\">General</div>\n            <div data-active='@(_tab == 2 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"() => GoToTab(2)\">Avatar</div>\n            <div data-active='@(_tab == 3 ? \"true\" : \"false\")' class=\"settings-menu-item\" @onclick=\"() => GoToTab(3)\">Credentials</div>\n        </section>\n\n        <section class=\"flex w-full flex-col divide-y divide-tab-outline\">\n            @if(_user is null)\n            {\n                <Spinner/>\n            } else if (_tab == 1)\n            {\n                <div class=\"flex flex-col py-5\">\n                    <label class=\"font-bold\">General settings</label>\n                    <label class=\"text-sm opacity-70\">All the most important settings for your profile, which do not belong to any other categories.</label>\n                </div>\n                <div class=\"settings-item\">\n                    <div class=\"flex flex-col text-sm\">\n                        <label class=\"font-bold opacity-90\">Advanced card settings after creation</label>\n                        <label class=\"w-4/5 max-w-2xl opacity-70\">Changes, whether the large modal for setting up a card should open\n                            after creating a card on the board.</label>\n                    </div>\n\n                    <input type=\"checkbox\" class=\"switch\" checked=@_user.AutomaticCardEdit @onchange=\"(e) => OnSettingChanged(e, x => x.AutomaticCardEdit)\">\n                </div>\n\n                <div class=\"settings-item\">\n                    <div class=\"flex flex-col text-sm\">\n                        <label class=\"font-bold opacity-90\">Delete without confirmation</label>\n                        <label class=\"w-4/5 max-w-2xl opacity-70\">This defines whether you should receive a confirmation pop-up whenever you\n                            initiate a deletion of an object.</label>\n                    </div>\n\n                    <input type=\"checkbox\" class=\"switch\" checked=@_user.InstantDelete @onchange=\"(e) => OnSettingChanged(e, x => x.InstantDelete)\">\n                </div>\n\n                <div class=\"settings-item\">\n                    <div class=\"flex flex-col text-sm\">\n                        <label class=\"font-bold opacity-90\">Automatic reminder on deadline</label>\n                        <label class=\"w-4/5 max-w-2xl opacity-70\">\n                            This option sets whether you will automatically be reminded about a card's deadline at the start of the day.\n                        </label>\n                    </div>\n\n                    <input type=\"checkbox\" class=\"switch\" checked=@_user.AutomaticDeadlineReminder @onchange=\"(e) => OnSettingChanged(e, x => x.AutomaticDeadlineReminder)\">\n                </div>\n\n                <div class=\"settings-item\">\n                    <div class=\"flex flex-col text-sm\">\n                        <label class=\"font-bold opacity-90\">Automatically assign self</label>\n                        <label class=\"w-4/5 max-w-2xl opacity-70\">\n                            This option sets whether you will automatically assign yourself to created cards.\n                        </label>\n                    </div>\n\n                    <input type=\"checkbox\" class=\"switch\" checked=@_user.AutomaticAssign @onchange=\"(e) => OnSettingChanged(e, x => x.AutomaticAssign)\">\n                </div>\n            } else if(_tab == 2)\n            {\n                <div class=\"flex flex-col py-5\">\n                    <label class=\"font-bold\">Avatar</label>\n                    <label class=\"text-sm opacity-70\">Here you can change your profile picture.</label>\n                </div>\n\n                <div class=\"flex flex-col items-center justify-around gap-2 py-5 md:flex-row\">\n                    <div class=\"flex flex-col items-center\">\n                        <div class=\"h-60 w-60 bg-cover bg-center\" \n                            style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_user.ProfilePictureFileName?v=@DateTime.Now.Ticks');\"/>\n                        <label>Full image</label>\n                    </div>\n\n                    <div class=\"flex flex-col items-center\">\n                        <div \n                            class=\"h-32 w-32 rounded-full bg-cover bg-center\" \n                            style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_user.ProfilePictureFileName?v=@DateTime.Now.Ticks');\"/>\n                        <label>Rounded version</label>\n                    </div>\n\n                    <div class=\"flex flex-col items-center\">\n                        <div \n                            class=\"h-8 w-8 rounded-full bg-cover bg-center\" \n                            style=\"background-image: url('@Constants.ACCESS_UPLOADED_IMAGES_PATH/@_user.ProfilePictureFileName?v=@DateTime.Now.Ticks');\"/>\n                        <label>Avatar version</label>\n                    </div>\n                </div>\n\n                <div class=\"py-5\">\n                    @if(_isLoading)\n                    {\n                        <Spinner/>\n                    }\n\n                    <div class=\"flex flex-row justify-end gap-5\">\n                        <label class=\"label-as-button w-min cursor-pointer px-5 py-2\" for=\"file-upload\">Upload</label>\n                        <InputFile class=\"hidden\" id=\"file-upload\" OnChange=\"OnFileChanged\"/>\n                        <button class=\"bg-cancel-button px-5 py-2 hover:bg-cancel-button-hover\" @onclick=\"RestoreToOriginal\">Reset</button>\n                    </div>\n                </div>\n            } else if(_tab == 3)\n            {\n                <NavigationLock ConfirmExternalNavigation=true OnBeforeInternalNavigation=\"OnBeforeInternalNavigation\"/>\n\n                <div class=\"flex flex-col py-5\">\n                    <label class=\"font-bold\">Credentials</label>\n                    @if(_user.NeedsNewCredentials)\n                    {\n                        <label class=\"text-sm text-orange-500 opacity-70\">This account is either using default credentials or they have been set up by the administrator, therefore they must be changed before going any further.</label>\n                    } else {\n                        <label class=\"text-sm opacity-70\">Here you can change your credentials.</label>\n                    }\n                </div>\n\n                <EditForm class=\"form py-5\" EditContext=\"_credentialsContext\" OnValidSubmit=\"OnCredentialsValidSubmit\">\n                    \n                    <DataAnnotationsValidator />\n\n                    <div class=\"form-group\">\n                        <Name For=\"() => _credentialsModel.OldEmailAddress\" />\n                        <InputText class=\"form-control\" @bind-Value=\"_credentialsModel.OldEmailAddress\" disabled/>\n                        <ValidationMessage For=\"() => _credentialsModel.OldEmailAddress\" />\n                    </div>\n\n                    <div class=\"form-group\">\n                        <Name For=\"() => _credentialsModel.NewEmailAddress\" />\n                        <InputText class=\"form-control\" @bind-Value=\"_credentialsModel.NewEmailAddress\" autofocus/>\n                        <ValidationMessage For=\"() => _credentialsModel.NewEmailAddress\" />\n                    </div>\n\n                    @if(!_user.NeedsNewCredentials)\n                    {\n                        <div class=\"form-group\">\n                            <Name For=\"() => _credentialsModel.OldPassword\" />\n                            <InputText type=\"password\" autocomplete=\"current-password\" autocapitalize=\"off\" spellcheck=\"false\" class=\"form-control\" @bind-Value=\"_credentialsModel.OldPassword\"/>\n                            <ValidationMessage For=\"() => _credentialsModel.OldPassword\" />\n                        </div>\n                    }\n\n                    <div class=\"form-group\">\n                        <Name For=\"() => _credentialsModel.NewPassword\" />\n                        <InputText type=\"password\" autocomplete=\"new-password\" autocapitalize=\"off\" spellcheck=\"false\" class=\"form-control\" @bind-Value=\"_credentialsModel.NewPassword\"/>\n                        <ValidationMessage For=\"() => _credentialsModel.NewPassword\" />\n                    </div>\n\n                    <div class=\"form-group\">\n                        <Name For=\"() => _credentialsModel.RepeatPassword\" />\n                        <InputText type=\"password\" autocomplete=\"new-password\" autocapitalize=\"off\" spellcheck=\"false\" class=\"form-control\" @bind-Value=\"_credentialsModel.RepeatPassword\"/>\n                        <ValidationMessage For=\"() => _credentialsModel.RepeatPassword\" />\n                    </div>\n\n                    <button class=\"auth-button\" type=\"submit\">Save</button>\n                </EditForm>\n            }\n        </section>\n    </section>\n</div>\n\n@code {\n    [CascadingParameter(Name = Constants.CascadingParameters.CurrentAccount)]\n    private User? _user { get; set; }\n\n    [Parameter]\n    public int? Tab { get; set; }\n\n    private int _tab = 1;\n\n    private IBrowserFile? _uploadedFile;\n\n    private bool _isLoading;\n    private CredentialsModel _credentialsModel = new();\n    private EditContext? _credentialsContext;\n    private ValidationMessageStore? _credentialsMessageStore;\n\n    protected override void OnParametersSet()\n    {\n        _credentialsContext = new EditContext(_credentialsModel);\n\n        if(!Tab.HasValue)\n            return;\n\n        GoToTab(Tab.Value);\n    }\n\n    protected override void OnAfterRender(bool firstRender)\n    {\n        if(!firstRender)\n            return;\n\n        ArgumentNullException.ThrowIfNull(_user);\n\n        _credentialsModel = new()\n        {\n            OldEmailAddress = _user.Email!,\n            NewEmailAddress = _user.NeedsNewCredentials ? string.Empty : _user.Email!\n        };\n        _credentialsContext = new EditContext(_credentialsModel);\n        _credentialsContext.OnValidationRequested += HandleValidationRequested;\n        _credentialsMessageStore = new(_credentialsContext);\n        StateHasChanged();\n    }\n\n    private void GoToTab(int tabNumber) \n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        if (tabNumber == _tab)\n            return;\n\n        if (_user.NeedsNewCredentials && tabNumber != 3) \n        {\n            OnAttemptedLeaveWhenDisallowed();\n            return;\n        }\n\n        _tab = Math.Clamp(tabNumber, 1, 3);\n    }\n\n    private async void OnSettingChanged(ChangeEventArgs e, Expression<Func<User, bool>> setter)\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        if (e.Value is not bool val)\n            return;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var user = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if (user is null)\n            return;\n\n        if (setter.Body is MemberExpression memberExpression && memberExpression.Member is PropertyInfo propertyInfo && propertyInfo.PropertyType == typeof(bool))\n            propertyInfo.SetValue(user, val);\n        else throw new Exception(\"Invalid property provided.\");\n\n        await db.SaveChangesAsync();\n\n        await RunNotification(typeof(UserSettings), OperationType.Edited);\n    }\n\n    private void ShowUploadError(string message)\n    {\n        _isLoading = false;\n        MainLayout.RunNotification(new Notification($\"File upload failed: {message}\", NotificationType.Fail));\n        StateHasChanged();\n    }\n\n    public async Task RestoreToOriginal() \n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        var avatarPath = await _avatarService.FetchAvatarAsync(_user.DisplayName);\n\n        using var db = _dbContextFactory.CreateDbContext();\n        var user = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n        if (user is null)\n            return;\n\n        user.ProfilePictureFileName = avatarPath;\n        await db.SaveChangesAsync();\n        _user = user;\n\n        StateHasChanged();\n\n        MainLayout.RunNotification(new Notification(\"Profile picture was reset to the default one.\"));\n    }\n\n    public async Task OnFileChanged(InputFileChangeEventArgs e)\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n        _isLoading = true;\n\n        if (!e.File.ContentType.Contains(\"image\"))\n        {\n            ShowUploadError(\"The file must be an image.\");\n            return;\n        }\n\n        if (e.File.Size > Constants.Limits.MAX_IMAGE_SIZE)\n        {\n            ShowUploadError(\"The file is too large.\");\n            return;\n        }\n\n        try\n        {\n            _uploadedFile = e.File;\n            var folderPath = Constants.SAVE_UPLOADED_IMAGES_PATH;\n\n            if (!Directory.Exists(folderPath))\n                Directory.CreateDirectory(folderPath);\n\n            var extension = _uploadedFile.Name[(_uploadedFile.Name.LastIndexOf('.') + 1)..];\n\n            string path;\n            string trustedFileName;\n            do\n            {\n                trustedFileName = Path.GetRandomFileName();\n                trustedFileName = trustedFileName[..trustedFileName.LastIndexOf('.')] + $\".{extension}\";\n\n                path = Path.Combine(folderPath, trustedFileName);\n            } while (File.Exists(path));\n\n            await using FileStream fs = new(path, FileMode.Create);\n            await e.File.OpenReadStream(Constants.Limits.MAX_IMAGE_SIZE).CopyToAsync(fs);\n\n            using var db = _dbContextFactory.CreateDbContext();\n            var user = await db.Users.FirstOrDefaultAsync(x => x.Id.Equals(_user.Id));\n\n            if(user is null)\n            {\n                ShowUploadError(\"An error occured. Try again later.\");\n                return;\n            }\n\n            user.ProfilePictureFileName = trustedFileName;\n            _user.ProfilePictureFileName = user.ProfilePictureFileName;\n\n            await db.SaveChangesAsync();\n\n            MainLayout.RunNotification(new Notification(\"Profile picture was changed.\"));\n            _isLoading = false;\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError($\"File upload failed, file name {e.File.Name}, error: {ex}\");\n            ShowUploadError(\"An error occured. Try again later.\");\n        }\n\n        StateHasChanged();\n    }\n\n    private void OnBeforeInternalNavigation(LocationChangingContext context)\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        if(!_user.NeedsNewCredentials)\n            return;\n\n        context.PreventNavigation();\n        OnAttemptedLeaveWhenDisallowed();\n    }\n\n    private void OnAttemptedLeaveWhenDisallowed()\n    {\n        MainLayout.RunNotification(new(\"You can't leave this page until you have changed your credentials.\", NotificationType.Fail));\n    }\n\n    private async void HandleValidationRequested(object? sender,\n        ValidationRequestedEventArgs args)\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        _credentialsMessageStore?.Clear();\n\n        if (!_user.NeedsNewCredentials)\n        {\n            if(!(await _userManager.CheckPasswordAsync(_user, _credentialsModel.OldPassword)))\n                _credentialsMessageStore?.Add(() => _credentialsModel.OldPassword, \"The old password you provided is incorrect. If you don't remember it, please reach out to an administrator to get it reset.\");\n        } else\n        {\n            if(string.IsNullOrWhiteSpace(_credentialsModel.NewPassword))\n                _credentialsMessageStore?.Add(() => _credentialsModel.NewPassword, \"A new password must be provided.\");\n\n        }\n    }\n\n    private async Task OnCredentialsValidSubmit()\n    {\n        ArgumentNullException.ThrowIfNull(_user);\n\n        var targetUser = await _userManager.FindByIdAsync(_user.Id.ToString());\n\n        ArgumentNullException.ThrowIfNull(targetUser);\n\n        if (!_credentialsModel.NewEmailAddress.Equals(_user.Email))\n        {\n            try\n            {\n                var result = await _userManager.SetUserNameAsync(targetUser, _credentialsModel.NewEmailAddress);\n\n                if (!result.Succeeded)\n                {\n                    foreach (var error in result.Errors)\n                        _credentialsMessageStore?.Add(() => _credentialsModel.NewEmailAddress, error.Description);\n\n                    _credentialsContext?.NotifyValidationStateChanged();\n                    return;\n                }\n\n                result = await _userManager.ChangeEmailAsync(targetUser, _credentialsModel.NewEmailAddress, await _userManager.GenerateChangeEmailTokenAsync(targetUser, _credentialsModel.NewEmailAddress));\n\n                if (!result.Succeeded)\n                {\n                    foreach (var error in result.Errors)\n                        _credentialsMessageStore?.Add(() => _credentialsModel.NewEmailAddress, error.Description);\n\n                    _credentialsContext?.NotifyValidationStateChanged();\n                    return;\n                }\n            }\n            catch (Exception ex)\n            {\n                _logger.LogError(ex, \"Failed to change e-mail.\");\n            }\n        }\n\n        if (!string.IsNullOrWhiteSpace(_credentialsModel.NewPassword))\n        {\n            try\n            {\n                var result = await _userManager.ResetPasswordAsync(targetUser, await _userManager.GeneratePasswordResetTokenAsync(targetUser), _credentialsModel.NewPassword);\n\n                if (!result.Succeeded)\n                {\n                    foreach (var error in result.Errors)\n                        _credentialsMessageStore?.Add(() => _credentialsModel.NewPassword, error.Description);\n\n                    _credentialsContext?.NotifyValidationStateChanged();\n                    return;\n                }\n            }\n            catch (Exception ex)\n            {\n                _logger.LogError(ex, \"Failed to change password.\");\n            }\n\n        }\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        await db.Users.Where(x => x.Id.Equals(targetUser.Id)).ExecuteUpdateAsync(x => x.SetProperty(y => y.NeedsNewCredentials, false));\n\n        targetUser.NeedsNewCredentials = false;\n        bool neededNewCredentials = _user.NeedsNewCredentials;\n        _user = targetUser;\n\n        if (neededNewCredentials) \n        {\n            MainLayout.RunNotification(new(\"Your credentials have been successfully set.\"));\n            _navigationManager.NavigateTo(\"/\");\n        }\n        else\n            MainLayout.RunNotification(new(\"User updated successfully.\"));\n    }\n\n\n    public void Dispose()\n    {\n        if (_credentialsContext is not null)\n        {\n            _credentialsContext.OnValidationRequested -= HandleValidationRequested;\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Components/Routes.razor",
    "content": "<CascadingAuthenticationState>\n    <Router AppAssembly=\"typeof(Program).Assembly\">\n        <Found Context=\"routeData\">\n            <AuthorizeRouteView RouteData=\"routeData\" DefaultLayout=\"typeof(Layout.MainLayout)\" />\n            <FocusOnNavigate RouteData=\"routeData\" Selector=\"h1\" />\n        </Found>\n        <NotFound>\n            <PageTitle>Not found</PageTitle>\n            <LayoutView Layout=\"@typeof(Layout.MainLayout)\">\n                <p role=\"alert\">Sorry, there's nothing at this address.</p>\n            </LayoutView>\n        </NotFound>\n    </Router>\n</CascadingAuthenticationState>"
  },
  {
    "path": "Ticky.Web/Components/_Imports.razor",
    "content": "@using System.Linq.Expressions;\n@using System.Net.Http\n@using System.Net.Http.Json\n@using System.Timers\n@using Devity.Blazor\n@using Devity.Extensions\n@using Microsoft.AspNetCore.Authorization\n@using Microsoft.AspNetCore.Components.Authorization\n@using Microsoft.AspNetCore.Components.Forms\n@using Microsoft.AspNetCore.Components.Routing\n@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage\n@using Microsoft.AspNetCore.Components.Web\n@using Microsoft.AspNetCore.SignalR.Client\n@using static Microsoft.AspNetCore.Components.Web.RenderMode\n@using Microsoft.AspNetCore.Components.Web.Virtualization\n@using Microsoft.JSInterop\n@using Ticky.Base.DTOs\n@using Ticky.Base.Models\n@using Ticky.Internal.Helpers\n@using Ticky.Web\n@using Ticky.Web.Components\n@using Ticky.Web.Components.Dialogs\n@using Ticky.Web.Components.Elements\n@using Ticky.Web.Components.Elements.Sortable\n@using Ticky.Web.Components.Layout\n@using Ticky.Web.Components.Pages.Abstractions\n"
  },
  {
    "path": "Ticky.Web/Controllers/AttachmentsController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\n\nnamespace Ticky.Web.Controllers;\n\n[Authorize]\n[Route(\"api/[controller]\")]\n[ApiController]\npublic class AttachmentsController : ControllerBase\n{\n    private readonly IDbContextFactory<DataContext> _dbContextFactory;\n    private readonly ILogger<AttachmentsController> _logger;\n\n    public AttachmentsController(\n        IDbContextFactory<DataContext> dbContextFactory,\n        ILogger<AttachmentsController> logger\n    )\n    {\n        _dbContextFactory = dbContextFactory;\n        _logger = logger;\n    }\n\n    [HttpGet(\"download/{*fileName}\")]\n    public async Task<IActionResult> Download(string fileName)\n    {\n        if (string.IsNullOrWhiteSpace(fileName))\n            return BadRequest();\n\n        var decodedFileName = WebUtility.UrlDecode(fileName);\n        string[] forbiddenChars = [\"..\", \"/\", \"\\\\\", \"\\n\", \"\\r\"];\n\n        if (forbiddenChars.Any(decodedFileName.Contains))\n            return BadRequest();\n\n        try\n        {\n            using var db = _dbContextFactory.CreateDbContext();\n            var attachment = await db.Attachments.FirstOrDefaultAsync(x =>\n                x.FileName == decodedFileName\n            );\n\n            if (attachment is null)\n                return NotFound();\n\n            var absolutePath = Path.GetFullPath(\n                Path.Combine(Constants.SAVE_UPLOADED_FILES_PATH, attachment.FileName)\n            );\n\n            if (!System.IO.File.Exists(absolutePath))\n                return NotFound();\n\n            var contentType = \"application/octet-stream\";\n            return PhysicalFile(absolutePath, contentType, attachment.OriginalName);\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(ex, \"Error while downloading attachment {FileName}\", decodedFileName);\n            return StatusCode(StatusCodes.Status500InternalServerError);\n        }\n    }\n\n    [HttpPost(\"upload\")]\n    [Consumes(\"multipart/form-data\")]\n    public async Task<IActionResult> Upload([FromForm] IFormFile? file, [FromForm] int cardId)\n    {\n        if (User is null)\n            return Unauthorized();\n\n        if (file is null)\n            return BadRequest(\"No file\");\n\n        if (file.Length > Constants.Limits.MAX_FILE_SIZE)\n            return BadRequest(\"File too large\");\n\n        var folderPath = Constants.SAVE_UPLOADED_FILES_PATH;\n\n        if (!Directory.Exists(folderPath))\n            Directory.CreateDirectory(folderPath);\n\n        try\n        {\n            var extension = Path.GetExtension(file.FileName);\n\n            if (string.IsNullOrWhiteSpace(extension))\n            {\n                extension = file.FileName.Contains('.')\n                    ? file.FileName[(file.FileName.LastIndexOf('.') + 1)..]\n                    : \"bin\";\n                if (!extension.StartsWith('.'))\n                    extension = \".\" + extension;\n            }\n\n            string trustedFileName;\n            string path;\n            do\n            {\n                trustedFileName = Path.GetRandomFileName();\n                trustedFileName = trustedFileName[..trustedFileName.LastIndexOf('.')] + extension;\n                path = Path.Combine(folderPath, trustedFileName);\n            } while (System.IO.File.Exists(path));\n\n            await using (var fs = new FileStream(path, FileMode.Create))\n            {\n                await file.CopyToAsync(fs);\n            }\n\n            using var db = _dbContextFactory.CreateDbContext();\n\n            var card = await db\n                .Cards.Include(x => x.Activities)\n                .Include(x => x.Attachments)\n                .FirstOrDefaultAsync(x => x.Id == cardId);\n\n            if (card is null)\n                return NotFound();\n\n            var attachment = new Attachment\n            {\n                CardId = cardId,\n                FileName = trustedFileName,\n                OriginalName = file.FileName\n            };\n\n            card.Attachments.Add(attachment);\n\n            var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty;\n            int userId = 0;\n\n            if (!string.IsNullOrWhiteSpace(userIdClaim))\n                int.TryParse(userIdClaim, out userId);\n\n            if (userId == 0)\n                return Unauthorized();\n\n            var safeFileName = WebUtility.HtmlEncode(file.FileName);\n\n            card.Activities.Add(\n                new Activity\n                {\n                    Text = $\"<b>uploaded</b> file named <b>{safeFileName}</b>\",\n                    UserId = userId,\n                    CardId = cardId\n                }\n            );\n\n            await db.SaveChangesAsync();\n\n            return Ok(new { success = true });\n        }\n        catch (Exception ex)\n        {\n            _logger.LogError(\n                ex,\n                \"An error occurred while uploading an attachment for card {CardId}\",\n                cardId\n            );\n\n            return StatusCode(StatusCodes.Status500InternalServerError);\n        }\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Controllers/HealthController.cs",
    "content": "namespace Ticky.Web.Controllers;\n\n[Route(\"api/[controller]\")]\n[ApiController]\npublic class HealthController : ControllerBase\n{\n    [HttpGet]\n    public IActionResult Get()\n    {\n        return Ok();\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/GlobalUsings.cs",
    "content": "global using System.ComponentModel.DataAnnotations;\nglobal using System.Drawing;\nglobal using System.Net;\nglobal using System.Security.Claims;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Identity;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.AspNetCore.Mvc.RazorPages;\nglobal using Microsoft.AspNetCore.SignalR;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using Microsoft.JSInterop;\nglobal using Ticky.Base;\nglobal using Ticky.Base.Converters;\nglobal using Ticky.Base.DTOs;\nglobal using Ticky.Base.Entities;\nglobal using Ticky.Base.Entities.Abstractions;\nglobal using Ticky.Base.Entities.Owned;\nglobal using Ticky.Base.Enums;\nglobal using Ticky.Base.Models;\nglobal using Ticky.Internal.Data;\nglobal using Ticky.Internal.Helpers;\nglobal using Ticky.Internal.Services;\nglobal using Ticky.Internal.Services.Hosted;\nglobal using Ticky.Web.Components;\nglobal using Ticky.Web.Hubs;\nglobal using Ticky.Web.Pages.Auth;\n"
  },
  {
    "path": "Ticky.Web/Hubs/UpdateHub.cs",
    "content": "namespace Ticky.Web.Hubs;\n\n[Authorize]\npublic class UpdateHub : Hub\n{\n    private readonly IDbContextFactory<DataContext> _dbContextFactory;\n\n    public UpdateHub(IDbContextFactory<DataContext> dbContextFactory)\n    {\n        _dbContextFactory = dbContextFactory;\n    }\n\n    private async Task<bool> IsUserInBoard(int boardId)\n    {\n        if (Context.User?.Identity?.IsAuthenticated != true)\n            return false;\n\n        using var db = _dbContextFactory.CreateDbContext();\n\n        var success = int.TryParse(\n            Context.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? string.Empty,\n            out int userId\n        );\n\n        if (!success)\n            return false;\n\n        return await db\n            .Boards.Include(x => x.Memberships)\n            .Include(x => x.Project)\n            .ThenInclude(x => x.Memberships)\n            .AnyAsync(b =>\n                b.Id == boardId\n                && (\n                    b.Memberships.Any(m => m.UserId == userId)\n                    || b.Project.Memberships.Any(pm => pm.UserId == userId)\n                )\n            );\n    }\n\n    public async Task BoardChange(int boardId, Guid pageId)\n    {\n        await Clients.Group($\"board_{boardId}\").SendAsync(nameof(BoardChange), boardId, pageId);\n    }\n\n    public async Task SubscribeBoard(int boardId)\n    {\n        if (!await IsUserInBoard(boardId))\n            return;\n\n        await Groups.AddToGroupAsync(Context.ConnectionId, $\"board_{boardId}\");\n    }\n}\n"
  },
  {
    "path": "Ticky.Web/Program.cs",
    "content": "using Devity.Mailing;\nusing Devity.NETCore.MailKit.Infrastructure.Internal;\nusing Microsoft.AspNetCore.DataProtection;\nusing Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;\nusing Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;\nusing Microsoft.AspNetCore.ResponseCompression;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add services to the container.\nbuilder.Services.AddRazorPages().WithRazorPagesRoot(\"/Components/Pages\");\nbuilder\n    .Services.AddRazorComponents()\n    .AddInteractiveServerComponents(options =>\n    {\n        options.DetailedErrors = true;\n    });\n\nbuilder.Services.AddDbContextFactory<DataContext>(options =>\n{\n    var connectionString =\n#if DEBUG\n        builder.Configuration.GetConnectionString(\"Development\")\n#else\n        builder.Configuration.GetConnectionString(\"Production\")\n#endif\n        ?? $\"Server={builder.Configuration.GetValue<string>(\"DB_HOST\")};Database={builder.Configuration.GetValue<string>(\"DB_NAME\", \"ticky\")};Uid={builder.Configuration.GetValue<string>(\"DB_USERNAME\", \"ticky\")};Pwd={builder.Configuration.GetValue<string>(\"DB_PASSWORD\")};\";\n    options.UseMySql(\n        connectionString,\n        ServerVersion.Create(\n            new Version(\"8.0.36\"),\n            Pomelo.EntityFrameworkCore.MySql.Infrastructure.ServerType.MySql\n        )\n    );\n#if DEBUG\n    options.EnableSensitiveDataLogging();\n#endif\n});\n\nbuilder\n    .Services.AddIdentity<User, IdentityRole<int>>(options =>\n    {\n        options.Password.RequiredLength = 6;\n        options.Password.RequireDigit = false;\n        options.Password.RequireUppercase = false;\n        options.Password.RequireLowercase = false;\n        options.Password.RequireNonAlphanumeric = false;\n        options.SignIn.RequireConfirmedEmail = false;\n    })\n    .AddEntityFrameworkStores<DataContext>()\n    .AddDefaultTokenProviders();\n\nbuilder.Services.ConfigureApplicationCookie(options =>\n{\n    options.ExpireTimeSpan = TimeSpan.FromDays(365);\n    options.SlidingExpiration = true;\n    options.LoginPath = \"/auth/login\";\n\n    options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;\n    options.Cookie.SameSite = SameSiteMode.Lax;\n    options.Cookie.HttpOnly = true;\n    options.Cookie.IsEssential = true;\n});\n\nbuilder.Services.Configure<DataProtectionTokenProviderOptions>(options =>\n{\n    options.TokenLifespan = TimeSpan.FromDays(7);\n});\n\nbuilder.Services.AddSignalR();\n\n// For signalR\nbuilder.Services.AddResponseCompression(opts =>\n{\n    opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat([\"application/octet-stream\"]);\n});\n\nConstants.FULLY_OFFLINE = builder.Configuration.GetValue(\"FULLY_OFFLINE\", true);\nConstants.DISABLE_USER_SIGNUPS = builder.Configuration.GetValue(\"DISABLE_USER_SIGNUPS\", false);\nConstants.SMTP_ENABLED = builder.Configuration.GetValue(\"SMTP_ENABLED\", false);\nConstants.BASE_URL = builder\n    .Configuration.GetValue(\"BASE_URL\", \"http://localhost:4088\")\n    .TrimEnd('/');\n\nvar mailKitOptions = builder.Configuration.GetSection(\"Email\").Get<MailKitOptions>();\n\nif (Constants.SMTP_ENABLED)\n{\n    if (mailKitOptions is null)\n    {\n        mailKitOptions = new MailKitOptions\n        {\n            Server = builder.Configuration.GetValue<string>(\"SMTP_HOST\"),\n            Port = builder.Configuration.GetValue<int>(\"SMTP_PORT\"),\n            SenderName = builder.Configuration.GetValue<string>(\"SMTP_DISPLAY_NAME\"),\n            SenderEmail = builder.Configuration.GetValue<string>(\"SMTP_EMAIL\"),\n            Password = builder.Configuration.GetValue<string>(\"SMTP_PASSWORD\"),\n            Account = builder.Configuration.GetValue<string>(\"SMTP_USERNAME\"),\n            Security = builder.Configuration.GetValue(\"SMTP_SECURITY\", true)\n        };\n    }\n\n    if (\n        mailKitOptions is null\n        || mailKitOptions.Server is null\n        || mailKitOptions.SenderEmail is null\n        || mailKitOptions.Password is null\n        || mailKitOptions.Port == 0\n        || mailKitOptions.SenderName is null\n        || mailKitOptions.Account is null\n    )\n    {\n        throw new InvalidOperationException(\n            \"Some parts of the SMTP configuration are missing. Please add the necessary environment variables. Check the repository for more information: https://github.com/dkorecko/Ticky.\"\n        );\n    }\n}\n\nbuilder.Services.AddScoped<CodeService>();\nbuilder.Services.AddDevityMailing<EmailService>(mailKitOptions!);\nbuilder.Services.AddScoped<AvatarService>();\nbuilder.Services.AddScoped<CardNumberingService>();\nbuilder.Services.AddScoped<SearchService>();\nbuilder.Services.AddScoped<TrelloImportService>();\nbuilder.Services.AddSingleton<InformationService>();\nbuilder.Services.AddHostedService<CleanupHostedService>();\nbuilder.Services.AddHostedService<SnoozeHostedService>();\nbuilder.Services.AddHostedService<RepeatHostedService>();\n\nif (Constants.SMTP_ENABLED)\n    builder.Services.AddHostedService<ReminderHostedService>();\n\nbuilder\n    .Services.AddDataProtection()\n    .SetApplicationName(\"ticky-application\")\n    .PersistKeysToDbContext<DataContext>()\n    .UseCryptographicAlgorithms(\n        new AuthenticatedEncryptorConfiguration\n        {\n            EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,\n            ValidationAlgorithm = ValidationAlgorithm.HMACSHA256\n        }\n    );\n\nbuilder.Services.AddHttpClient();\nbuilder.Services.AddHttpContextAccessor();\n\nbuilder.Services.AddAuthorization(options =>\n{\n    options.AddPolicy(\n        Constants.Policies.RequireAdmin,\n        policy => policy.RequireClaim(ClaimTypes.Role, Constants.Roles.Admin).Build()\n    );\n});\n\nbuilder.Services.AddControllers();\n\n#if !DEBUG\n// NOTE: In production, the application is expected to run behind a reverse proxy (e.g., Nginx, Traefik) that terminates HTTPS.\n//       Binding to HTTP here is intentional and safe in that context. Do NOT expose this endpoint directly to the internet.\nbuilder.WebHost.UseUrls(\"http://0.0.0.0:8080\");\n#endif\n\nvar app = builder.Build();\n\n// For signalR\napp.UseResponseCompression();\n\nusing (var scope = app.Services.CreateScope())\n{\n    var dbContext = scope.ServiceProvider.GetRequiredService<DataContext>()!;\n\n    if (dbContext.Database.IsRelational())\n        dbContext.Database.Migrate();\n\n    DataSeeder.Seed(scope.ServiceProvider).GetAwaiter().GetResult();\n    DataMigrator.Seed(scope.ServiceProvider).GetAwaiter().GetResult();\n}\n\n// Configure the HTTP request pipeline.\nif (!app.Environment.IsDevelopment())\n{\n    app.UseExceptionHandler(\"/Error\", createScopeForErrors: true);\n}\n\napp.UseAntiforgery();\n\napp.UseStaticFiles();\n\napp.UseAuthentication();\napp.UseAuthorization();\n\napp.MapControllers();\napp.MapRazorComponents<App>().AddInteractiveServerRenderMode();\napp.MapRazorPages();\napp.MapHub<UpdateHub>(Constants.Hubs.UPDATE_HUB);\n\napp.Run();\n"
  },
  {
    "path": "Ticky.Web/Properties/launchSettings.json",
    "content": "{\n  \"$schema\": \"https://json.schemastore.org/launchsettings.json\",\n    \"profiles\": {\n      \"http\": {\n        \"commandName\": \"Project\",\n        \"dotnetRunMessages\": true,\n        \"launchBrowser\": false,\n        \"applicationUrl\": \"http://localhost:5035\",\n        \"environmentVariables\": {\n          \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n        }\n      },\n      \"https\": {\n        \"commandName\": \"Project\",\n        \"dotnetRunMessages\": true,\n        \"launchBrowser\": false,\n        \"applicationUrl\": \"https://localhost:7225\",\n        \"environmentVariables\": {\n          \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n        }\n      }\n    }\n  }\n"
  },
  {
    "path": "Ticky.Web/Ticky.Web.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>net9.0</TargetFramework>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <UserSecretsId>70e04088-d9e4-4290-bf43-1907c0b90a4b</UserSecretsId>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Devity.Blazor\" Version=\"2025.5.7.2024\" />\n    <PackageReference Include=\"Devity.Extensions\" Version=\"2026.1.4.1450\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Identity.EntityFrameworkCore\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.SignalR.Client\" Version=\"9.0.9\" />\n    <PackageReference Include=\"Microsoft.EntityFrameworkCore.Design\" Version=\"9.0.9\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Pomelo.EntityFrameworkCore.MySql\" Version=\"9.0.0-preview.3.efcore.9.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Ticky.Base\\Ticky.Base.csproj\" />\n    <ProjectReference Include=\"..\\Ticky.Internal\\Ticky.Internal.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Content Update=\"wwwroot\\emails\\DeadlineReminder.html\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\emails\\ForgottenPassword.html\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\emails\\Reminder.html\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\emails\\VerifyEmail.html\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\images\\question_mark_avatar.png\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\images\\ticky.png\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"wwwroot\\information.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n  </ItemGroup>\n\n  <ItemGroup>\n    <Folder Include=\"wwwroot\\uploaded\\files\\\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Ticky.Web/app.css",
    "content": "﻿@import \"tailwindcss\";\n@config \"./tailwind.config.js\";\n\n@theme {\n    --color-primary: oklch(0.595 0.2538 297);\n    --color-primary-hover: oklch(0.381 0.176 304.987); /* purple 900 */\n\n    --color-card-bg: oklch(0.968 0.007 247.896); /* slate 100 */\n    --color-card-diff-bg: oklch(0.923 0.003 48.717); /* stone 200 */\n    --color-card-blocked-bg: oklch(0.901 0.076 70.697); /* orange 200 */\n    --color-card-blocked-text: oklch(0.444 0.177 26.899); /* red 800 */\n    --color-add-outline: oklch(0.551 0.027 264.364); /* gray 500 */\n    --color-add-outline-hover: oklch(0.21 0.034 264.665); /* gray 900 */\n\n    --color-column-limit-reached: oklch(0.885 0.062 18.334); /* red 200 */\n    --color-cancel-button: oklch(0.551 0.027 264.364); /* gray 500 */\n    --color-cancel-button-hover: oklch(0.373 0.034 259.733); /* gray 700 */\n    --color-red-button: oklch(0.637 0.237 25.331); /* red 500 */\n    --color-red-button-hover: oklch(0.505 0.213 27.518); /* red 700 */\n    --color-green-button: oklch(0.527 0.154 150.069); /* green 700 */\n    --color-green-button-hover: oklch(0.393 0.095 152.535); /* green 900 */\n    --color-backdrop: oklch(0.446 0.03 256.802); /* gray 600 */\n    --color-modal: #fff; /* white */\n\n    --color-dropdown-option: oklch(0.872 0.01 258.338); /* gray 300 */\n    --color-icon: oklch(0.551 0.027 264.364); /* gray 500 */\n    --color-icon-hover: oklch(0.21 0.034 264.665); /* gray 900 */\n    --color-icon-bg-hover: oklch(0.704 0.04 256.788); /* slate 400 */\n    --color-card-icon-bg-hover: oklch(0.872 0.01 258.338); /* gray 300 */\n    --color-disabled-icon: oklch(0.872 0.01 258.338); /* gray 300 */\n\n    --color-label-text: #fff; /* white */\n\n    --color-card-data-points: oklch(0.551 0.027 264.364); /* gray 500 */\n\n    --color-search-bar: oklch(0.929 0.013 255.508); /* slate 200 */\n    --color-full-dropdown: oklch(0.929 0.013 255.508); /* slate 200 */\n    --color-full-dropdown-hover: oklch(0.869 0.022 252.894); /* slate 300 */\n    --color-full-dropdown-disabled: oklch(0.967 0.003 264.542); /* gray 100 */\n\n    --color-typing-outline: oklch(0.809 0.105 251.813); /* blue 300 */\n\n    --color-card-heading: oklch(0.709 0.01 56.259); /* stone 400 */\n\n    --color-auth-bottom-text: oklch(0.707 0.022 261.325); /* gray 400 */\n    --color-auth-bg: #fff; /* white */\n\n    --color-tab-outline: oklch(0.707 0.022 261.325); /* gray 400 */\n\n    --color-nav-link: oklch(0.554 0.046 257.417); /* slate 500 */\n    --color-nav-link-hover: oklch(0.595 0.2538 297); /* primary */\n    --color-avatar-ring: #fff; /* white */\n\n    --color-app-bg: oklch(0.869 0.022 252.894); /* slate 300 */\n\n    --color-button-text: oklch(0.968 0.007 247.896); /* slate 100 */\n    --color-app-text: #000; /* black */\n    --color-card-heading: oklch(0.279 0.041 260.031); /* slate 800 */\n\n    --color-auth-gradient-start: oklch(0.777 0.152 181.912); /* teal 400 */\n    --color-auth-gradient-via: oklch(0.714 0.203 305.504); /* purple 400 */\n    --color-auth-gradient-to: oklch(0.595 0.2538 297); /* primary */\n\n    --color-checkbox-bg: oklch(0.707 0.022 261.325); /* gray 400 */\n    --color-divide: oklch(0.928 0.006 264.531); /* gray 200 */\n\n    --color-card-header-highlight: #000; /* black */\n    --color-card-edit-label: oklch(0.554 0.046 257.417); /* slate 500 */\n\n    --color-person-label-bg: oklch(0.929 0.013 255.508); /* slate 200 */\n\n    --text-2xs: 0.65rem;\n    --breakpoint-xs: 30rem;\n    --breakpoint-2xs: 20rem;\n}\n\n@layer base {\n    [data-theme='dark'] {\n        --color-primary: oklch(0.595 0.2538 297); /* purple 500 - same as light mode, as it's a vibrant accent */\n        --color-primary-hover: oklch(0.700 0.280 297); /* Lighter hover for contrast on dark background */\n\n        --color-card-bg: oklch(0.25 0.005 247.896); /* Dark slate for card backgrounds */\n        --color-card-diff-bg: oklch(0.32 0.005 48.717); /* Slightly lighter dark stone for differentiated cards */\n        --color-card-blocked-bg: oklch(0.258 0.092 26.042); /* red 950 */\n        --color-card-blocked-text: oklch(0.808 0.114 19.571); /* red 300 */\n\n        --color-add-outline: oklch(0.8 0.027 264.364); /* Darker gray for outlines */\n        --color-add-outline-hover: oklch(0.95 0.034 264.665); /* Lighter gray on hover */\n\n        --color-column-limit-reached: oklch(0.258 0.092 26.042); /* red 950 */\n        --color-cancel-button: oklch(0.45 0.027 264.364); /* Darker gray for cancel button */\n        --color-cancel-button-hover: oklch(0.60 0.034 259.733); /* Lighter gray on hover */\n        --color-red-button: oklch(0.637 0.237 25.331); /* red 500 */\n        --color-red-button-hover: oklch(0.700 0.250 25.331); /* Lighter red on hover */\n        --color-green-button: oklch(0.527 0.154 150.069); /* green 700 */\n        --color-green-button-hover: oklch(0.723 0.219 149.579); /* green 500 */\n        --color-backdrop: oklch(0.1 0.01 256.802); /* Very dark gray for backdrop, near black */\n        --color-modal: oklch(0.20 0.01 247.896); /* Dark background for modals */\n\n        --color-dropdown-option: oklch(0.35 0.01 258.338); /* Darker gray for dropdown options */\n        --color-icon: oklch(0.65 0.027 264.364); /* Lighter gray for icons */\n        --color-icon-hover: oklch(0.85 0.034 264.665); /* Even lighter gray on hover */\n        --color-icon-bg-hover: oklch(0.4 0.01 252.894);\n        --color-card-icon-bg-hover: oklch(0.4 0.005 247.896);\n        --color-disabled-icon: oklch(0.50 0.027 264.364); /* Darker gray for disabled icons */\n\n        --color-label-text: #fff; /* Off-white for labels */\n\n        --color-card-data-points: oklch(0.70 0.027 264.364); /* Lighter gray for data points */\n\n        --color-search-bar: oklch(0.22 0.01 255.508); /* Dark slate for search bar */\n        --color-full-dropdown: oklch(0.22 0.01 255.508); /* slate 200 */\n        --color-full-dropdown-hover: oklch(0.35 0.01 255.508); /* slate 300 */\n        --color-full-dropdown-disabled: oklch(0.33 0.01 255.508);\n        --color-typing-outline: oklch(0.65 0.105 251.813); /* Brighter blue for typing outline */\n\n        --color-card-heading: oklch(0.50 0.01 56.259); /* Darker stone for card headings */\n\n        --color-auth-bottom-text: oklch(0.55 0.022 261.325); /* Mid-gray for authentication bottom text */\n        --color-auth-bg: oklch(0.15 0.01 247.896); /* Very dark background for auth pages */\n\n        --color-tab-outline: oklch(0.55 0.022 261.325); /* Mid-gray for tab outlines */\n\n        --color-nav-link: oklch(0.85 0.04 257.417); /* Lighter slate for navigation links */\n        --color-nav-link-hover: oklch(0.8 0.2538 297); /* primary */\n        --color-avatar-ring: oklch(0.90 0.01 250); /* Off-white for avatar ring */\n\n        --color-app-bg: oklch(0.12 0.01 252.894); /* Very dark main app background */\n\n        --color-button-text: oklch(0.968 0.007 247.896); /* slate 100 */\n        --color-app-text: oklch(0.95 0.01 250); /* Near white for main app text */\n        --color-card-heading: #fff; /* white */\n\n        --color-auth-gradient-start: oklch(0.277 0.046 192.524); /* teal 950 */\n        --color-auth-gradient-via: oklch(0.291 0.149 302.717); /* purple 950 */\n        --color-auth-gradient-to: oklch(0.284 0.109 3.907); /* pink 950 */\n\n        --color-checkbox-bg: oklch(0.12 0.01 252.894); /* Very dark main app background */\n        --color-divide: oklch(0.45 0.006 264.531);\n        --color-card-header-highlight: #fff; /* white */\n        --color-card-edit-label: oklch(0.95 0.01 250);\n        --color-person-label-bg: oklch(0.20 0.01 247.896);\n        --color-scrollbar-track: oklch(0.15 0.005 250); /* Very dark gray for scrollbar track */\n        --color-scrollbar-thumb: oklch(0.50 0.01 250); /* Mid-gray for scrollbar thumb */\n        --color-scrollbar-thumb-hover: oklch(0.65 0.015 250); /* Lighter gray for scrollbar thumb on hover */\n    }\n\n    *,\n    ::after,\n    ::before,\n    ::backdrop,\n    ::file-selector-button {\n        border-color: var(--color-divide, currentColor);\n    }\n}\n    \n/* Regular checkbox styling */\ninput[type=\"checkbox\"]:not(.switch) {\n    @apply h-4 w-4 min-w-4 cursor-pointer appearance-none rounded-sm border-1 border-add-outline bg-card-bg transition-all;\n}\n\ninput[type=\"checkbox\"]:not(.switch):checked {\n    @apply bg-primary;\n    background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\");\n}\n\noption {\n    @apply bg-modal;\n}\n\nhtml[data-theme='dark'] {\n    color-scheme: dark;\n}\n\n[data-theme='dark'] body {\n    color-scheme: dark;\n}\n\n[data-theme='dark'] ::-webkit-scrollbar-track {\n    background: var(--color-scrollbar-track);\n    border-radius: 10px;\n}\n\n[data-theme='dark'] ::-webkit-scrollbar-thumb {\n    background: var(--color-scrollbar-thumb);\n    border-radius: 10px;\n    border: 3px solid var(--color-scrollbar-track);\n}\n\n    [data-theme='dark'] ::-webkit-scrollbar-thumb:hover {\n        background: var(--color-scrollbar-thumb-hover);\n    }\n\n/* For Firefox \n Note: Firefox's scrollbar-color doesn't support a separate hover state for the thumb */\n[data-theme='dark'] html {\n    scrollbar-width: thin;\n    scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);\n}\n\nh1:focus {\n    outline: none;\n}\n\nbody, input {\n    font-family: 'Noto Sans';\n}\n\ninput {\n    outline: none;\n}\n\n.nav-links {\n    @apply flex;\n    @apply flex-row;\n    @apply gap-10;\n    @apply self-center;\n    @apply text-nav-link;\n    @apply text-sm tracking-wide;\n}\n\n.nav-link {\n    @apply transition-all;\n    @apply select-none;\n    @apply hover:text-nav-link-hover;\n    @apply cursor-pointer;\n    @apply z-10;\n}\n\n.active {\n    @apply text-nav-link-hover;\n}\n\n.avatar {\n    @apply w-8 min-w-8;\n    @apply h-8 min-h-8;\n\n    @apply bg-center;\n    background-size: cover;\n    border-radius: 50%;\n\n    @apply cursor-pointer;\n}\n\n.stack-avatars {\n    margin-left: -1rem;\n    @apply outline-1 outline-avatar-ring;\n}\n\n.avatar-border {\n    @apply shadow-primary shadow-[0_0_2px_2px];\n}\n\n.max-h-visible-screen {\n    @apply max-h-[calc(var(--vvh)*100-(var(--spacing)*6)-(var(--spacing)*2)*6-(var(--spacing)*8)*2-17px)];\n}\n\n.h-board-content {\n    @apply h-[calc(var(--vvh)*100-(var(--spacing)*6)*4-1px)];\n}\n\n.h-visible-screen {\n    @apply h-[calc(var(--vvh)*100)];\n}\n\n.board-column {\n    @apply flex w-64 flex-col items-center;\n}\n\n.task-card {\n    @apply mb-2 flex w-full cursor-pointer flex-col gap-3 rounded-lg bg-card-bg p-3 shadow-sm select-none data-[blocked=True]:bg-card-blocked-bg;\n}\n\n.to-task-card {\n    @apply select-none data-[active=True]:flex data-[active=True]:flex-col data-[active=True]:gap-3 data-[active=True]:bg-card-bg data-[active=True]:p-3 data-[active=True]:shadow-sm\n        data-[active=True]:outline-0;\n}\n\n.priority {\n    @apply text-2xs w-fit cursor-pointer rounded-lg px-3 py-1 font-bold;\n}\n\n.label {\n    @apply text-2xs flex w-fit cursor-pointer items-center justify-center rounded-lg px-3 py-1 font-bold;\n}\n\n.card-data-point {\n    @apply flex cursor-pointer flex-row items-center justify-center gap-1 whitespace-nowrap;\n}\n\nbutton, button[type='submit'], .label-as-button {\n    @apply rounded-lg bg-primary py-2 text-xs text-button-text transition-all ease-in-out hover:bg-primary-hover;\n}\n\nbutton, .label-as-button > label {\n    @apply cursor-pointer;\n}\n\nbutton, .label-as-button > i {\n    @apply cursor-pointer;\n}\n\n::-webkit-scrollbar {\n    @apply h-2 w-2;\n  }\n  \n  /* Track */\n  ::-webkit-scrollbar-track {\n    background: #f1f1f1;\n  }\n  \n  /* Handle */\n  ::-webkit-scrollbar-thumb {\n    background: #888;\n    border-radius: 8px;\n  }\n  \n  /* Handle on hover */\n  ::-webkit-scrollbar-thumb:hover {\n    background: #555;\n  }\n\n.auth-bg {\n    @apply from-auth-gradient-start via-auth-gradient-via to-auth-gradient-to flex h-full w-full items-center justify-center bg-gradient-to-tr;\n}\n\n.auth-inp-label {\n    @apply flex flex-col gap-2;\n}\n\n.auth-label {\n    @apply ml-1 text-sm font-semibold opacity-80;\n}\n\n.auth-input {\n    @apply h-8 w-full border-b-2 border-gray-600 bg-auth-bg px-2 text-sm font-normal\n        transition-all ease-in-out focus:border-primary;\n}\n\n.auth-button {\n    @apply mt-5 !rounded-full !text-base;\n}\n\n.auth-card {\n    @apply mx-2 flex w-[30rem] flex-col gap-12 rounded-lg bg-auth-bg px-12 py-24 shadow-2xl;\n}\n\n.auth-form {\n    @apply flex flex-col gap-6;\n}\n\n.auth-link {\n    @apply cursor-pointer text-xs font-semibold text-primary transition-all hover:text-primary-hover;\n}\n\ninput[type=\"checkbox\"].switch{\n\tfont-size: 30px;\n\t-webkit-appearance: none;\n\t   -moz-appearance: none;\n\t        appearance: none;\n\twidth: 3.5em;\n\theight: 1.5em;\n\tbackground: transparent;\n\tborder-radius: 3em;\n\tposition: relative;\n\tcursor: pointer;\n\t-webkit-transition: all .2s ease-in-out;\n\ttransition: all .2s ease-in-out;\n    @apply scale-50 bg-checkbox-bg shadow-sm;\n  }\n\n[data-theme='dark'] input[type=\"checkbox\"].switch {\n    @apply outline-3;\n}\n  \n  input[type=\"checkbox\"].switch:checked{\n\t@apply bg-primary;\n  }\n  \n  input[type=\"checkbox\"].switch:after{\n\tposition: absolute;\n\tcontent: \"\";\n\twidth: 1.5em;\n\theight: 1.5em;\n\tborder-radius: 50%;\n\tbackground: #fff;\n\t-webkit-transform: scale(.7);\n\t        transform: scale(.7);\n\tleft: 0;\n\t-webkit-transition: all .2s ease-in-out;\n\ttransition: all .2s ease-in-out;\n  }\n  \n  input[type=\"checkbox\"].switch:checked:after{\n\tleft: calc(100% - 1.5em);\n  }\n\n.settings-menu-item {\n    @apply cursor-pointer rounded-lg px-2 py-1 transition-all ease-in-out select-none hover:bg-slate-400 hover:text-app-text data-[active=true]:bg-primary-hover/20 data-[active=true]:text-primary-hover;\n}\n\n.settings-item {\n    @apply flex flex-col justify-between gap-2 py-5 lg:flex-row lg:items-center;\n}\n\n@utility add {\n    @apply flex cursor-pointer flex-col items-center justify-center gap-5 text-add-outline outline-1 outline-add-outline transition-all ease-in-out outline-dashed hover:text-add-outline-hover hover:outline-add-outline-hover;\n}\n\n.board-card-create {\n    @apply add h-min w-full rounded-lg px-5 py-5 select-none sm:w-72;\n}\n\n    .add label {\n        @apply cursor-pointer;\n    }\n\n@utility icon-button {\n    @apply cursor-pointer rounded-lg bg-transparent p-1 text-add-outline transition-all ease-in-out hover:text-add-outline-hover hover:bg-icon-bg-hover;\n}\n\n.card-button {\n    @apply icon-button hover:!bg-card-icon-bg-hover;\n}\n\n.board-card {\n    @apply flex h-min w-full cursor-pointer flex-col rounded-lg bg-card-bg px-5 py-5 shadow-sm transition-all ease-in-out select-none hover:shadow-xl sm:w-72 /*hover:scale-105*/;\n}\n\n[data-theme=''] .board-card {\n    @apply hover:shadow-gray-500;\n}\n\n[data-theme='dark'] .board-card {\n    @apply hover:outline-1;\n}\n\n\n.board-card-data-point {\n    @apply text-card-data-points flex cursor-pointer flex-row items-center justify-start gap-3 pl-1 text-xs;\n}\n\n    .board-card-data-point > i {\n        @apply w-4 text-base;\n    }\n\n.field-validation-error, .validation-message {\n    @apply text-xs text-red-button;\n}\n\n.form {\n    @apply flex flex-col gap-3;\n}\n\n.form-group {\n    @apply flex flex-col gap-1 transition-all;\n}\n\n    .form-group > label {\n        @apply text-xs font-light;\n    }\n\n    .form-group > .form-control {\n        @apply border-b-2 border-purple-300 px-2 py-1 text-sm transition-all focus:border-primary;\n    }\n\n.dragging {\n    @apply rotate-6 transition-transform;\n}\n\n.edit-task-label {\n    @apply text-card-edit-label w-24 overflow-hidden text-sm font-normal;\n}\n\n.edit-task-item {\n    @apply flex flex-row flex-wrap items-center gap-2 text-sm font-medium;\n}\n\n.person-label {\n    @apply bg-person-label-bg flex flex-row items-center\n        justify-center gap-1 overflow-hidden rounded-full p-1 text-xs font-normal;\n}\n\n[data-theme='dark'] .person-label, [data-theme='dark'] .card-label {\n    @apply outline-2;\n}\n\n    .person-label > div {\n        @apply w-5;\n        @apply h-5;\n    \n        @apply bg-center;\n        background-size: cover;\n        border-radius: 50%;\n    }\n\n.card-label {\n    @apply bg-person-label-bg flex flex-row items-center\n        justify-center gap-2 overflow-hidden rounded-full px-2 py-1.5 text-xs font-normal;\n}\n\n.edit-icon {\n    @apply cursor-pointer\n    p-2 text-xs text-add-outline outline-add-outline transition-all ease-in-out\n    hover:text-add-outline-hover hover:outline-add-outline-hover;\n}\n\n.icon {\n    @apply p-2 text-xs text-add-outline outline-add-outline transition-all ease-in-out;\n}\n\n.priority-selector-item {\n    @apply flex cursor-pointer flex-row items-center justify-between px-2 py-2 transition-all ease-in-out hover:bg-dropdown-option;\n}\n\n.person-link {\n    @apply cursor-pointer items-stretch rounded-lg bg-blue-600 px-1 pb-0.5 whitespace-pre-wrap text-white transition-all ease-in-out hover:bg-blue-700;\n}\n\n.plk-dd-spacing {\n    @apply h-1 transition-all;\n}\n\n.plk-dd-spacing-dragged-over {\n    @apply h-24 transition-all;\n}\n\n.plk-dd-inprogess > * {\n    pointer-events: none;\n}\n\n.element-spinner {\n    border-radius: 50%;\n    animation: spin 1s ease-in-out infinite;\n    @apply h-10 w-10 border-4 border-card-bg border-t-primary data-[small=True]:h-5 data-[small=True]:w-5;\n}\n\n@keyframes spin {\n    to {\n        transform: rotate(360deg);\n    }\n}\n\n.element-spinner-wrapper {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n    height: 100%;\n}\n\n.valid.modified:not([type=checkbox]) {\n    outline: 1px solid #26b050;\n}\n\n.invalid {\n    outline: 1px solid #e50000;\n}\n\n.blazor-error-boundary {\n    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;\n    padding: 1rem 1rem 1rem 3.7rem;\n    color: white;\n}\n\n    .blazor-error-boundary::after {\n        content: \"An error has occurred.\"\n    }\n\n#blazor-error-ui {\n    color-scheme: light only;\n    background: lightyellow;\n    bottom: 0;\n    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);\n    box-sizing: border-box;\n    display: none;\n    left: 0;\n    padding: 0.6rem 1.25rem 0.7rem 1.25rem;\n    position: fixed;\n    width: 100%;\n    z-index: 1000;\n}\n\n    #blazor-error-ui .dismiss {\n        cursor: pointer;\n        position: absolute;\n        right: 0.75rem;\n        top: 0.5rem;\n    }\n\n.tooltip-wrapper {\n    position: relative;\n    display: inline-block;\n    cursor: help;\n}\n\n.tooltip-span {\n    visibility: hidden;\n    position: absolute;\n    width: 120px;\n    bottom: 100%;\n    left: 50%;\n    margin-left: -60px;\n    background-color: #363636;\n    color: #fff;\n    text-align: center;\n    padding: 5px 0;\n    border-radius: 6px;\n    z-index: 1;\n}\n\n    .tooltip-span::after {\n        content: \"\";\n        position: absolute;\n        top: 100%;\n        left: 50%;\n        margin-left: -5px;\n        border-width: 5px;\n        border-style: solid;\n        border-color: #555 transparent transparent transparent;\n    }\n\n.tooltip-wrapper:hover .tooltip-span {\n    visibility: visible;\n}\n\n.sortable-chosen {\n    @apply animate-pulse;\n}\n\n[data-theme='dark'] .task-card.sortable-chosen {\n    @apply border-2;\n}\n\n.dropdown-animate {\n  transition: opacity 0.1s cubic-bezier(0.4,0,0.2,1), transform 0.1s cubic-bezier(0.4,0,0.2,1);\n  transform: translateY(-10px);\n  opacity: 0;\n}\n.dropdown-animate-in {\n  transform: translateY(0);\n  opacity: 1;\n}"
  },
  {
    "path": "Ticky.Web/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\",\n      \"Microsoft.EntityFrameworkCore.Database.Command\": \"Warning\"\n    }\n  }\n}\n"
  },
  {
    "path": "Ticky.Web/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\",\n      \"Microsoft.EntityFrameworkCore.Database.Command\": \"Warning\"\n    }\n  }\n}\n"
  },
  {
    "path": "Ticky.Web/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@tailwindcss/cli\": \"^4.1.8\",\n    \"tailwindcss\": \"^4.1.7\"\n  }\n}\n"
  },
  {
    "path": "Ticky.Web/tailwind.config.js",
    "content": "/** @type {import('tailwindcss').Config} */\nmodule.exports = {\n  content: [\n        \"./**/*.{razor,cshtml,html}\",\n    \"./wwwroot/information.json\",\n    // Explicitly exclude email templates\n    \"!./wwwroot/emails/**/*\"\n  ]\n}"
  },
  {
    "path": "Ticky.Web/tailwind.extension.json",
    "content": "{\n  \"$schema\": \"https://raw.githubusercontent.com/theron-wang/VS2022-Editor-Support-for-Tailwind-CSS/refs/heads/main/tailwind.extension.schema.json\",\n  \"BuildFiles\": [\n    {\n      \"Input\": \"app.css\",\n      \"Output\": \"wwwroot\\\\css\\\\app.css\"\n    }\n  ],\n  \"PackageConfigurationFile\": null,\n  \"CustomRegexes\": {\n    \"Razor\": {\n      \"Override\": false,\n      \"Values\": []\n    },\n    \"HTML\": {\n      \"Override\": false,\n      \"Values\": []\n    },\n    \"JavaScript\": {\n      \"Override\": false,\n      \"Values\": []\n    }\n  },\n  \"UseCli\": false\n}"
  },
  {
    "path": "Ticky.Web/wwwroot/css/app.css",
    "content": "/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n  :root, :host {\n    --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n      \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n    --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n      \"Courier New\", monospace;\n    --color-red-500: oklch(63.7% 0.237 25.331);\n    --color-orange-500: oklch(70.5% 0.213 47.604);\n    --color-yellow-500: oklch(79.5% 0.184 86.047);\n    --color-green-400: oklch(79.2% 0.209 151.711);\n    --color-green-500: oklch(72.3% 0.219 149.579);\n    --color-sky-500: oklch(68.5% 0.169 237.323);\n    --color-blue-400: oklch(70.7% 0.165 254.624);\n    --color-blue-600: oklch(54.6% 0.245 262.881);\n    --color-blue-700: oklch(48.8% 0.243 264.376);\n    --color-blue-800: oklch(42.4% 0.199 265.638);\n    --color-purple-300: oklch(82.7% 0.119 306.383);\n    --color-pink-300: oklch(82.3% 0.12 346.018);\n    --color-pink-500: oklch(65.6% 0.241 354.308);\n    --color-slate-200: oklch(92.9% 0.013 255.508);\n    --color-slate-400: oklch(70.4% 0.04 256.788);\n    --color-gray-100: oklch(96.7% 0.003 264.542);\n    --color-gray-300: oklch(87.2% 0.01 258.338);\n    --color-gray-400: oklch(70.7% 0.022 261.325);\n    --color-gray-500: oklch(55.1% 0.027 264.364);\n    --color-gray-600: oklch(44.6% 0.03 256.802);\n    --color-stone-500: oklch(55.3% 0.013 58.071);\n    --color-white: #fff;\n    --spacing: 0.25rem;\n    --container-2xl: 42rem;\n    --container-3xl: 48rem;\n    --container-4xl: 56rem;\n    --text-xs: 0.75rem;\n    --text-xs--line-height: calc(1 / 0.75);\n    --text-sm: 0.875rem;\n    --text-sm--line-height: calc(1.25 / 0.875);\n    --text-base: 1rem;\n    --text-base--line-height: calc(1.5 / 1);\n    --text-xl: 1.25rem;\n    --text-xl--line-height: calc(1.75 / 1.25);\n    --text-2xl: 1.5rem;\n    --text-2xl--line-height: calc(2 / 1.5);\n    --text-3xl: 1.875rem;\n    --text-3xl--line-height: calc(2.25 / 1.875);\n    --font-weight-light: 300;\n    --font-weight-normal: 400;\n    --font-weight-medium: 500;\n    --font-weight-semibold: 600;\n    --font-weight-bold: 700;\n    --font-weight-extrabold: 800;\n    --tracking-wide: 0.025em;\n    --radius-xs: 0.125rem;\n    --radius-sm: 0.25rem;\n    --radius-md: 0.375rem;\n    --radius-lg: 0.5rem;\n    --radius-2xl: 1rem;\n    --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n    --animate-spin: spin 1s linear infinite;\n    --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n    --default-transition-duration: 150ms;\n    --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n    --default-font-family: var(--font-sans);\n    --default-mono-font-family: var(--font-mono);\n    --color-primary: oklch(0.595 0.2538 297);\n    --color-primary-hover: oklch(0.381 0.176 304.987);\n    --color-card-bg: oklch(0.968 0.007 247.896);\n    --color-card-diff-bg: oklch(0.923 0.003 48.717);\n    --color-card-blocked-bg: oklch(0.901 0.076 70.697);\n    --color-card-blocked-text: oklch(0.444 0.177 26.899);\n    --color-add-outline: oklch(0.551 0.027 264.364);\n    --color-add-outline-hover: oklch(0.21 0.034 264.665);\n    --color-column-limit-reached: oklch(0.885 0.062 18.334);\n    --color-cancel-button: oklch(0.551 0.027 264.364);\n    --color-cancel-button-hover: oklch(0.373 0.034 259.733);\n    --color-red-button: oklch(0.637 0.237 25.331);\n    --color-red-button-hover: oklch(0.505 0.213 27.518);\n    --color-green-button: oklch(0.527 0.154 150.069);\n    --color-green-button-hover: oklch(0.393 0.095 152.535);\n    --color-backdrop: oklch(0.446 0.03 256.802);\n    --color-modal: #fff;\n    --color-dropdown-option: oklch(0.872 0.01 258.338);\n    --color-icon: oklch(0.551 0.027 264.364);\n    --color-icon-bg-hover: oklch(0.704 0.04 256.788);\n    --color-card-icon-bg-hover: oklch(0.872 0.01 258.338);\n    --color-disabled-icon: oklch(0.872 0.01 258.338);\n    --color-label-text: #fff;\n    --color-card-data-points: oklch(0.551 0.027 264.364);\n    --color-search-bar: oklch(0.929 0.013 255.508);\n    --color-full-dropdown: oklch(0.929 0.013 255.508);\n    --color-full-dropdown-hover: oklch(0.869 0.022 252.894);\n    --color-full-dropdown-disabled: oklch(0.967 0.003 264.542);\n    --color-typing-outline: oklch(0.809 0.105 251.813);\n    --color-card-heading: oklch(0.279 0.041 260.031);\n    --color-auth-bottom-text: oklch(0.707 0.022 261.325);\n    --color-auth-bg: #fff;\n    --color-tab-outline: oklch(0.707 0.022 261.325);\n    --color-nav-link: oklch(0.554 0.046 257.417);\n    --color-nav-link-hover: oklch(0.595 0.2538 297);\n    --color-avatar-ring: #fff;\n    --color-app-bg: oklch(0.869 0.022 252.894);\n    --color-button-text: oklch(0.968 0.007 247.896);\n    --color-app-text: #000;\n    --color-auth-gradient-start: oklch(0.777 0.152 181.912);\n    --color-auth-gradient-via: oklch(0.714 0.203 305.504);\n    --color-auth-gradient-to: oklch(0.595 0.2538 297);\n    --color-checkbox-bg: oklch(0.707 0.022 261.325);\n    --color-divide: oklch(0.928 0.006 264.531);\n    --color-card-header-highlight: #000;\n    --color-card-edit-label: oklch(0.554 0.046 257.417);\n    --color-person-label-bg: oklch(0.929 0.013 255.508);\n    --text-2xs: 0.65rem;\n  }\n}\n@layer base {\n  *, ::after, ::before, ::backdrop, ::file-selector-button {\n    box-sizing: border-box;\n    margin: 0;\n    padding: 0;\n    border: 0 solid;\n  }\n  html, :host {\n    line-height: 1.5;\n    -webkit-text-size-adjust: 100%;\n    tab-size: 4;\n    font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n    font-feature-settings: var(--default-font-feature-settings, normal);\n    font-variation-settings: var(--default-font-variation-settings, normal);\n    -webkit-tap-highlight-color: transparent;\n  }\n  hr {\n    height: 0;\n    color: inherit;\n    border-top-width: 1px;\n  }\n  abbr:where([title]) {\n    -webkit-text-decoration: underline dotted;\n    text-decoration: underline dotted;\n  }\n  h1, h2, h3, h4, h5, h6 {\n    font-size: inherit;\n    font-weight: inherit;\n  }\n  a {\n    color: inherit;\n    -webkit-text-decoration: inherit;\n    text-decoration: inherit;\n  }\n  b, strong {\n    font-weight: bolder;\n  }\n  code, kbd, samp, pre {\n    font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n    font-feature-settings: var(--default-mono-font-feature-settings, normal);\n    font-variation-settings: var(--default-mono-font-variation-settings, normal);\n    font-size: 1em;\n  }\n  small {\n    font-size: 80%;\n  }\n  sub, sup {\n    font-size: 75%;\n    line-height: 0;\n    position: relative;\n    vertical-align: baseline;\n  }\n  sub {\n    bottom: -0.25em;\n  }\n  sup {\n    top: -0.5em;\n  }\n  table {\n    text-indent: 0;\n    border-color: inherit;\n    border-collapse: collapse;\n  }\n  :-moz-focusring {\n    outline: auto;\n  }\n  progress {\n    vertical-align: baseline;\n  }\n  summary {\n    display: list-item;\n  }\n  ol, ul, menu {\n    list-style: none;\n  }\n  img, svg, video, canvas, audio, iframe, embed, object {\n    display: block;\n    vertical-align: middle;\n  }\n  img, video {\n    max-width: 100%;\n    height: auto;\n  }\n  button, input, select, optgroup, textarea, ::file-selector-button {\n    font: inherit;\n    font-feature-settings: inherit;\n    font-variation-settings: inherit;\n    letter-spacing: inherit;\n    color: inherit;\n    border-radius: 0;\n    background-color: transparent;\n    opacity: 1;\n  }\n  :where(select:is([multiple], [size])) optgroup {\n    font-weight: bolder;\n  }\n  :where(select:is([multiple], [size])) optgroup option {\n    padding-inline-start: 20px;\n  }\n  ::file-selector-button {\n    margin-inline-end: 4px;\n  }\n  ::placeholder {\n    opacity: 1;\n  }\n  @supports (not (-webkit-appearance: -apple-pay-button))  or (contain-intrinsic-size: 1px) {\n    ::placeholder {\n      color: currentcolor;\n      @supports (color: color-mix(in lab, red, red)) {\n        color: color-mix(in oklab, currentcolor 50%, transparent);\n      }\n    }\n  }\n  textarea {\n    resize: vertical;\n  }\n  ::-webkit-search-decoration {\n    -webkit-appearance: none;\n  }\n  ::-webkit-date-and-time-value {\n    min-height: 1lh;\n    text-align: inherit;\n  }\n  ::-webkit-datetime-edit {\n    display: inline-flex;\n  }\n  ::-webkit-datetime-edit-fields-wrapper {\n    padding: 0;\n  }\n  ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n    padding-block: 0;\n  }\n  ::-webkit-calendar-picker-indicator {\n    line-height: 1;\n  }\n  :-moz-ui-invalid {\n    box-shadow: none;\n  }\n  button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n    appearance: button;\n  }\n  ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n    height: auto;\n  }\n  [hidden]:where(:not([hidden=\"until-found\"])) {\n    display: none !important;\n  }\n}\n@layer utilities {\n  .visible {\n    visibility: visible;\n  }\n  .absolute {\n    position: absolute;\n  }\n  .fixed {\n    position: fixed;\n  }\n  .relative {\n    position: relative;\n  }\n  .static {\n    position: static;\n  }\n  .top-0 {\n    top: calc(var(--spacing) * 0);\n  }\n  .right-0 {\n    right: calc(var(--spacing) * 0);\n  }\n  .right-5 {\n    right: calc(var(--spacing) * 5);\n  }\n  .bottom-5 {\n    bottom: calc(var(--spacing) * 5);\n  }\n  .left-0 {\n    left: calc(var(--spacing) * 0);\n  }\n  .z-10 {\n    z-index: 10;\n  }\n  .z-20 {\n    z-index: 20;\n  }\n  .z-50 {\n    z-index: 50;\n  }\n  .m-5 {\n    margin: calc(var(--spacing) * 5);\n  }\n  .mt-1 {\n    margin-top: calc(var(--spacing) * 1);\n  }\n  .mt-5 {\n    margin-top: calc(var(--spacing) * 5);\n  }\n  .mr-2 {\n    margin-right: calc(var(--spacing) * 2);\n  }\n  .mr-12 {\n    margin-right: calc(var(--spacing) * 12);\n  }\n  .mr-auto {\n    margin-right: auto;\n  }\n  .\\!ml-\\[-0\\.8rem\\] {\n    margin-left: -0.8rem !important;\n  }\n  .ml-1 {\n    margin-left: calc(var(--spacing) * 1);\n  }\n  .ml-2 {\n    margin-left: calc(var(--spacing) * 2);\n  }\n  .ml-3 {\n    margin-left: calc(var(--spacing) * 3);\n  }\n  .ml-4 {\n    margin-left: calc(var(--spacing) * 4);\n  }\n  .ml-6 {\n    margin-left: calc(var(--spacing) * 6);\n  }\n  .ml-12 {\n    margin-left: calc(var(--spacing) * 12);\n  }\n  .ml-\\[-5px\\] {\n    margin-left: -5px;\n  }\n  .ml-auto {\n    margin-left: auto;\n  }\n  .add {\n    display: flex;\n    cursor: pointer;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    gap: calc(var(--spacing) * 5);\n    color: var(--color-add-outline);\n    outline-style: var(--tw-outline-style);\n    outline-width: 1px;\n    outline-color: var(--color-add-outline);\n    transition-property: all;\n    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n    transition-duration: var(--tw-duration, var(--default-transition-duration));\n    --tw-ease: var(--ease-in-out);\n    transition-timing-function: var(--ease-in-out);\n    --tw-outline-style: dashed;\n    outline-style: dashed;\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-add-outline-hover);\n      }\n    }\n    &:hover {\n      @media (hover: hover) {\n        outline-color: var(--color-add-outline-hover);\n      }\n    }\n  }\n  .block {\n    display: block;\n  }\n  .flex {\n    display: flex;\n  }\n  .grid {\n    display: grid;\n  }\n  .hidden {\n    display: none;\n  }\n  .inline-block {\n    display: inline-block;\n  }\n  .table {\n    display: table;\n  }\n  .\\!h-6 {\n    height: calc(var(--spacing) * 6) !important;\n  }\n  .\\!h-10 {\n    height: calc(var(--spacing) * 10) !important;\n  }\n  .\\!h-32 {\n    height: calc(var(--spacing) * 32) !important;\n  }\n  .h-0\\.5 {\n    height: calc(var(--spacing) * 0.5);\n  }\n  .h-1 {\n    height: calc(var(--spacing) * 1);\n  }\n  .h-2 {\n    height: calc(var(--spacing) * 2);\n  }\n  .h-3 {\n    height: calc(var(--spacing) * 3);\n  }\n  .h-4 {\n    height: calc(var(--spacing) * 4);\n  }\n  .h-8 {\n    height: calc(var(--spacing) * 8);\n  }\n  .h-16 {\n    height: calc(var(--spacing) * 16);\n  }\n  .h-24 {\n    height: calc(var(--spacing) * 24);\n  }\n  .h-32 {\n    height: calc(var(--spacing) * 32);\n  }\n  .h-60 {\n    height: calc(var(--spacing) * 60);\n  }\n  .h-\\[90vh\\] {\n    height: 90vh;\n  }\n  .h-full {\n    height: 100%;\n  }\n  .h-min {\n    height: min-content;\n  }\n  .max-h-\\[80vh\\] {\n    max-height: 80vh;\n  }\n  .min-h-12 {\n    min-height: calc(var(--spacing) * 12);\n  }\n  .min-h-\\[1rem\\] {\n    min-height: 1rem;\n  }\n  .\\!w-6 {\n    width: calc(var(--spacing) * 6) !important;\n  }\n  .\\!w-10 {\n    width: calc(var(--spacing) * 10) !important;\n  }\n  .\\!w-32 {\n    width: calc(var(--spacing) * 32) !important;\n  }\n  .w-0 {\n    width: calc(var(--spacing) * 0);\n  }\n  .w-2 {\n    width: calc(var(--spacing) * 2);\n  }\n  .w-4 {\n    width: calc(var(--spacing) * 4);\n  }\n  .w-4\\/5 {\n    width: calc(4/5 * 100%);\n  }\n  .w-8 {\n    width: calc(var(--spacing) * 8);\n  }\n  .w-9 {\n    width: calc(var(--spacing) * 9);\n  }\n  .w-24 {\n    width: calc(var(--spacing) * 24);\n  }\n  .w-32 {\n    width: calc(var(--spacing) * 32);\n  }\n  .w-36 {\n    width: calc(var(--spacing) * 36);\n  }\n  .w-60 {\n    width: calc(var(--spacing) * 60);\n  }\n  .w-72 {\n    width: calc(var(--spacing) * 72);\n  }\n  .w-80 {\n    width: calc(var(--spacing) * 80);\n  }\n  .w-100 {\n    width: calc(var(--spacing) * 100);\n  }\n  .w-full {\n    width: 100%;\n  }\n  .w-min {\n    width: min-content;\n  }\n  .w-screen {\n    width: 100vw;\n  }\n  .max-w-2 {\n    max-width: calc(var(--spacing) * 2);\n  }\n  .max-w-2xl {\n    max-width: var(--container-2xl);\n  }\n  .max-w-4xl {\n    max-width: var(--container-4xl);\n  }\n  .max-w-\\[1300px\\] {\n    max-width: 1300px;\n  }\n  .max-w-full {\n    max-width: 100%;\n  }\n  .min-w-0 {\n    min-width: calc(var(--spacing) * 0);\n  }\n  .min-w-2 {\n    min-width: calc(var(--spacing) * 2);\n  }\n  .min-w-64 {\n    min-width: calc(var(--spacing) * 64);\n  }\n  .min-w-80 {\n    min-width: calc(var(--spacing) * 80);\n  }\n  .flex-grow {\n    flex-grow: 1;\n  }\n  .grow {\n    flex-grow: 1;\n  }\n  .border-separate {\n    border-collapse: separate;\n  }\n  .border-spacing-3 {\n    --tw-border-spacing-x: calc(var(--spacing) * 3);\n    --tw-border-spacing-y: calc(var(--spacing) * 3);\n    border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);\n  }\n  .border-spacing-x-5 {\n    --tw-border-spacing-x: calc(var(--spacing) * 5);\n    border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);\n  }\n  .border-spacing-y-1 {\n    --tw-border-spacing-y: calc(var(--spacing) * 1);\n    border-spacing: var(--tw-border-spacing-x) var(--tw-border-spacing-y);\n  }\n  .transform {\n    transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n  }\n  .animate-pulse {\n    animation: var(--animate-pulse);\n  }\n  .icon-button {\n    cursor: pointer;\n    border-radius: var(--radius-lg);\n    background-color: transparent;\n    padding: calc(var(--spacing) * 1);\n    color: var(--color-add-outline);\n    transition-property: all;\n    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n    transition-duration: var(--tw-duration, var(--default-transition-duration));\n    --tw-ease: var(--ease-in-out);\n    transition-timing-function: var(--ease-in-out);\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-icon-bg-hover);\n      }\n    }\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-add-outline-hover);\n      }\n    }\n  }\n  .\\!cursor-help {\n    cursor: help !important;\n  }\n  .\\!cursor-not-allowed {\n    cursor: not-allowed !important;\n  }\n  .cursor-move {\n    cursor: move;\n  }\n  .cursor-not-allowed {\n    cursor: not-allowed;\n  }\n  .cursor-pointer {\n    cursor: pointer;\n  }\n  .resize {\n    resize: both;\n  }\n  .resize-none {\n    resize: none;\n  }\n  .flex-col {\n    flex-direction: column;\n  }\n  .flex-row {\n    flex-direction: row;\n  }\n  .flex-wrap {\n    flex-wrap: wrap;\n  }\n  .content-between {\n    align-content: space-between;\n  }\n  .content-start {\n    align-content: flex-start;\n  }\n  .items-center {\n    align-items: center;\n  }\n  .items-start {\n    align-items: flex-start;\n  }\n  .justify-around {\n    justify-content: space-around;\n  }\n  .justify-between {\n    justify-content: space-between;\n  }\n  .justify-center {\n    justify-content: center;\n  }\n  .justify-end {\n    justify-content: flex-end;\n  }\n  .justify-start {\n    justify-content: flex-start;\n  }\n  .gap-1 {\n    gap: calc(var(--spacing) * 1);\n  }\n  .gap-2 {\n    gap: calc(var(--spacing) * 2);\n  }\n  .gap-3 {\n    gap: calc(var(--spacing) * 3);\n  }\n  .gap-4 {\n    gap: calc(var(--spacing) * 4);\n  }\n  .gap-5 {\n    gap: calc(var(--spacing) * 5);\n  }\n  .gap-6 {\n    gap: calc(var(--spacing) * 6);\n  }\n  .gap-8 {\n    gap: calc(var(--spacing) * 8);\n  }\n  .gap-10 {\n    gap: calc(var(--spacing) * 10);\n  }\n  .gap-x-3 {\n    column-gap: calc(var(--spacing) * 3);\n  }\n  .gap-y-1 {\n    row-gap: calc(var(--spacing) * 1);\n  }\n  .divide-x {\n    :where(& > :not(:last-child)) {\n      --tw-divide-x-reverse: 0;\n      border-inline-style: var(--tw-border-style);\n      border-inline-start-width: calc(1px * var(--tw-divide-x-reverse));\n      border-inline-end-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));\n    }\n  }\n  .divide-y {\n    :where(& > :not(:last-child)) {\n      --tw-divide-y-reverse: 0;\n      border-bottom-style: var(--tw-border-style);\n      border-top-style: var(--tw-border-style);\n      border-top-width: calc(1px * var(--tw-divide-y-reverse));\n      border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n    }\n  }\n  .divide-tab-outline {\n    :where(& > :not(:last-child)) {\n      border-color: var(--color-tab-outline);\n    }\n  }\n  .self-center {\n    align-self: center;\n  }\n  .truncate {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .overflow-auto {\n    overflow: auto;\n  }\n  .overflow-hidden {\n    overflow: hidden;\n  }\n  .overflow-x-auto {\n    overflow-x: auto;\n  }\n  .overflow-x-clip {\n    overflow-x: clip;\n  }\n  .overflow-x-hidden {\n    overflow-x: hidden;\n  }\n  .overflow-y-auto {\n    overflow-y: auto;\n  }\n  .overflow-y-scroll {\n    overflow-y: scroll;\n  }\n  .rounded {\n    border-radius: 0.25rem;\n  }\n  .rounded-2xl {\n    border-radius: var(--radius-2xl);\n  }\n  .rounded-full {\n    border-radius: calc(infinity * 1px);\n  }\n  .rounded-lg {\n    border-radius: var(--radius-lg);\n  }\n  .rounded-md {\n    border-radius: var(--radius-md);\n  }\n  .rounded-sm {\n    border-radius: var(--radius-sm);\n  }\n  .rounded-xs {\n    border-radius: var(--radius-xs);\n  }\n  .border {\n    border-style: var(--tw-border-style);\n    border-width: 1px;\n  }\n  .border-2 {\n    border-style: var(--tw-border-style);\n    border-width: 2px;\n  }\n  .border-b-2 {\n    border-bottom-style: var(--tw-border-style);\n    border-bottom-width: 2px;\n  }\n  .border-l-2 {\n    border-left-style: var(--tw-border-style);\n    border-left-width: 2px;\n  }\n  .border-tab-outline {\n    border-color: var(--color-tab-outline);\n  }\n  .border-white {\n    border-color: var(--color-white);\n  }\n  .border-t-tab-outline {\n    border-top-color: var(--color-tab-outline);\n  }\n  .\\!bg-cancel-button {\n    background-color: var(--color-cancel-button) !important;\n  }\n  .\\!bg-green-button {\n    background-color: var(--color-green-button) !important;\n  }\n  .\\!bg-red-button {\n    background-color: var(--color-red-button) !important;\n  }\n  .bg-add-outline {\n    background-color: var(--color-add-outline);\n  }\n  .bg-app-bg {\n    background-color: var(--color-app-bg);\n  }\n  .bg-backdrop\\/0 {\n    background-color: color-mix(in srgb, oklch(0.446 0.03 256.802) 0%, transparent);\n    @supports (color: color-mix(in lab, red, red)) {\n      background-color: color-mix(in oklab, var(--color-backdrop) 0%, transparent);\n    }\n  }\n  .bg-blue-400 {\n    background-color: var(--color-blue-400);\n  }\n  .bg-cancel-button {\n    background-color: var(--color-cancel-button);\n  }\n  .bg-card-bg {\n    background-color: var(--color-card-bg);\n  }\n  .bg-card-diff-bg {\n    background-color: var(--color-card-diff-bg);\n  }\n  .bg-column-limit-reached {\n    background-color: var(--color-column-limit-reached);\n  }\n  .bg-full-dropdown {\n    background-color: var(--color-full-dropdown);\n  }\n  .bg-full-dropdown-disabled {\n    background-color: var(--color-full-dropdown-disabled);\n  }\n  .bg-gray-100 {\n    background-color: var(--color-gray-100);\n  }\n  .bg-gray-300 {\n    background-color: var(--color-gray-300);\n  }\n  .bg-gray-400 {\n    background-color: var(--color-gray-400);\n  }\n  .bg-green-400 {\n    background-color: var(--color-green-400);\n  }\n  .bg-green-500 {\n    background-color: var(--color-green-500);\n  }\n  .bg-modal {\n    background-color: var(--color-modal);\n  }\n  .bg-modal\\/0 {\n    background-color: color-mix(in srgb, #fff 0%, transparent);\n    @supports (color: color-mix(in lab, red, red)) {\n      background-color: color-mix(in oklab, var(--color-modal) 0%, transparent);\n    }\n  }\n  .bg-orange-500 {\n    background-color: var(--color-orange-500);\n  }\n  .bg-pink-300 {\n    background-color: var(--color-pink-300);\n  }\n  .bg-pink-500 {\n    background-color: var(--color-pink-500);\n  }\n  .bg-primary {\n    background-color: var(--color-primary);\n  }\n  .bg-red-500 {\n    background-color: var(--color-red-500);\n  }\n  .bg-search-bar {\n    background-color: var(--color-search-bar);\n  }\n  .bg-sky-500 {\n    background-color: var(--color-sky-500);\n  }\n  .bg-slate-200 {\n    background-color: var(--color-slate-200);\n  }\n  .bg-yellow-500 {\n    background-color: var(--color-yellow-500);\n  }\n  .bg-cover {\n    background-size: cover;\n  }\n  .bg-center {\n    background-position: center;\n  }\n  .\\!p-0 {\n    padding: calc(var(--spacing) * 0) !important;\n  }\n  .p-0\\.5 {\n    padding: calc(var(--spacing) * 0.5);\n  }\n  .p-2 {\n    padding: calc(var(--spacing) * 2);\n  }\n  .p-4 {\n    padding: calc(var(--spacing) * 4);\n  }\n  .p-5 {\n    padding: calc(var(--spacing) * 5);\n  }\n  .px-1 {\n    padding-inline: calc(var(--spacing) * 1);\n  }\n  .px-2 {\n    padding-inline: calc(var(--spacing) * 2);\n  }\n  .px-3 {\n    padding-inline: calc(var(--spacing) * 3);\n  }\n  .px-4 {\n    padding-inline: calc(var(--spacing) * 4);\n  }\n  .px-5 {\n    padding-inline: calc(var(--spacing) * 5);\n  }\n  .px-7 {\n    padding-inline: calc(var(--spacing) * 7);\n  }\n  .px-8 {\n    padding-inline: calc(var(--spacing) * 8);\n  }\n  .px-10 {\n    padding-inline: calc(var(--spacing) * 10);\n  }\n  .px-12 {\n    padding-inline: calc(var(--spacing) * 12);\n  }\n  .py-0\\.5 {\n    padding-block: calc(var(--spacing) * 0.5);\n  }\n  .py-1 {\n    padding-block: calc(var(--spacing) * 1);\n  }\n  .py-1\\.5 {\n    padding-block: calc(var(--spacing) * 1.5);\n  }\n  .py-2 {\n    padding-block: calc(var(--spacing) * 2);\n  }\n  .py-3 {\n    padding-block: calc(var(--spacing) * 3);\n  }\n  .py-5 {\n    padding-block: calc(var(--spacing) * 5);\n  }\n  .py-6 {\n    padding-block: calc(var(--spacing) * 6);\n  }\n  .py-14 {\n    padding-block: calc(var(--spacing) * 14);\n  }\n  .pt-5 {\n    padding-top: calc(var(--spacing) * 5);\n  }\n  .pr-1 {\n    padding-right: calc(var(--spacing) * 1);\n  }\n  .pr-2 {\n    padding-right: calc(var(--spacing) * 2);\n  }\n  .pb-3 {\n    padding-bottom: calc(var(--spacing) * 3);\n  }\n  .pl-3 {\n    padding-left: calc(var(--spacing) * 3);\n  }\n  .pl-5 {\n    padding-left: calc(var(--spacing) * 5);\n  }\n  .text-center {\n    text-align: center;\n  }\n  .text-end {\n    text-align: end;\n  }\n  .text-start {\n    text-align: start;\n  }\n  .align-middle {\n    vertical-align: middle;\n  }\n  .\\!text-base {\n    font-size: var(--text-base) !important;\n    line-height: var(--tw-leading, var(--text-base--line-height)) !important;\n  }\n  .text-2xl {\n    font-size: var(--text-2xl);\n    line-height: var(--tw-leading, var(--text-2xl--line-height));\n  }\n  .text-3xl {\n    font-size: var(--text-3xl);\n    line-height: var(--tw-leading, var(--text-3xl--line-height));\n  }\n  .text-sm {\n    font-size: var(--text-sm);\n    line-height: var(--tw-leading, var(--text-sm--line-height));\n  }\n  .text-xl {\n    font-size: var(--text-xl);\n    line-height: var(--tw-leading, var(--text-xl--line-height));\n  }\n  .text-xs {\n    font-size: var(--text-xs);\n    line-height: var(--tw-leading, var(--text-xs--line-height));\n  }\n  .text-2xs {\n    font-size: var(--text-2xs);\n  }\n  .text-\\[16rem\\] {\n    font-size: 16rem;\n  }\n  .font-bold {\n    --tw-font-weight: var(--font-weight-bold);\n    font-weight: var(--font-weight-bold);\n  }\n  .font-extrabold {\n    --tw-font-weight: var(--font-weight-extrabold);\n    font-weight: var(--font-weight-extrabold);\n  }\n  .font-light {\n    --tw-font-weight: var(--font-weight-light);\n    font-weight: var(--font-weight-light);\n  }\n  .font-medium {\n    --tw-font-weight: var(--font-weight-medium);\n    font-weight: var(--font-weight-medium);\n  }\n  .font-normal {\n    --tw-font-weight: var(--font-weight-normal);\n    font-weight: var(--font-weight-normal);\n  }\n  .font-semibold {\n    --tw-font-weight: var(--font-weight-semibold);\n    font-weight: var(--font-weight-semibold);\n  }\n  .break-normal {\n    overflow-wrap: normal;\n    word-break: normal;\n  }\n  .break-words {\n    overflow-wrap: break-word;\n  }\n  .text-ellipsis {\n    text-overflow: ellipsis;\n  }\n  .whitespace-nowrap {\n    white-space: nowrap;\n  }\n  .\\!text-disabled-icon {\n    color: var(--color-disabled-icon) !important;\n  }\n  .\\!text-red-button {\n    color: var(--color-red-button) !important;\n  }\n  .text-add-outline {\n    color: var(--color-add-outline);\n  }\n  .text-app-text {\n    color: var(--color-app-text);\n  }\n  .text-auth-bottom-text {\n    color: var(--color-auth-bottom-text);\n  }\n  .text-blue-600 {\n    color: var(--color-blue-600);\n  }\n  .text-card-blocked-text {\n    color: var(--color-card-blocked-text);\n  }\n  .text-card-data-points {\n    color: var(--color-card-data-points);\n  }\n  .text-card-heading {\n    color: var(--color-card-heading);\n  }\n  .text-gray-400 {\n    color: var(--color-gray-400);\n  }\n  .text-gray-500 {\n    color: var(--color-gray-500);\n  }\n  .text-green-500 {\n    color: var(--color-green-500);\n  }\n  .text-icon {\n    color: var(--color-icon);\n  }\n  .text-label-text {\n    color: var(--color-label-text);\n  }\n  .text-nav-link {\n    color: var(--color-nav-link);\n  }\n  .text-orange-500 {\n    color: var(--color-orange-500);\n  }\n  .text-primary {\n    color: var(--color-primary);\n  }\n  .text-red-500 {\n    color: var(--color-red-500);\n  }\n  .text-red-button {\n    color: var(--color-red-button);\n  }\n  .text-stone-500 {\n    color: var(--color-stone-500);\n  }\n  .text-white {\n    color: var(--color-white);\n  }\n  .capitalize {\n    text-transform: capitalize;\n  }\n  .underline {\n    text-decoration-line: underline;\n  }\n  .opacity-0 {\n    opacity: 0%;\n  }\n  .opacity-40 {\n    opacity: 40%;\n  }\n  .opacity-60 {\n    opacity: 60%;\n  }\n  .opacity-70 {\n    opacity: 70%;\n  }\n  .opacity-90 {\n    opacity: 90%;\n  }\n  .shadow {\n    --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n    box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  }\n  .shadow-2xl {\n    --tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));\n    box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  }\n  .shadow-lg {\n    --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n    box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  }\n  .shadow-sm {\n    --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n    box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  }\n  .outline-0 {\n    outline-style: var(--tw-outline-style);\n    outline-width: 0px;\n  }\n  .outline-1 {\n    outline-style: var(--tw-outline-style);\n    outline-width: 1px;\n  }\n  .outline-2 {\n    outline-style: var(--tw-outline-style);\n    outline-width: 2px;\n  }\n  .outline-add-outline {\n    outline-color: var(--color-add-outline);\n  }\n  .outline-typing-outline {\n    outline-color: var(--color-typing-outline);\n  }\n  .filter {\n    filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n  }\n  .transition {\n    transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;\n    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n    transition-duration: var(--tw-duration, var(--default-transition-duration));\n  }\n  .transition-all {\n    transition-property: all;\n    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n    transition-duration: var(--tw-duration, var(--default-transition-duration));\n  }\n  .transition-colors {\n    transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n    transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n    transition-duration: var(--tw-duration, var(--default-transition-duration));\n  }\n  .ease-in-out {\n    --tw-ease: var(--ease-in-out);\n    transition-timing-function: var(--ease-in-out);\n  }\n  .select-none {\n    -webkit-user-select: none;\n    user-select: none;\n  }\n  .hover\\:border-add-outline {\n    &:hover {\n      @media (hover: hover) {\n        border-color: var(--color-add-outline);\n      }\n    }\n  }\n  .hover\\:\\!bg-cancel-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-cancel-button-hover) !important;\n      }\n    }\n  }\n  .hover\\:\\!bg-green-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-green-button-hover) !important;\n      }\n    }\n  }\n  .hover\\:\\!bg-red-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-red-button-hover) !important;\n      }\n    }\n  }\n  .hover\\:bg-cancel-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-cancel-button-hover);\n      }\n    }\n  }\n  .hover\\:bg-dropdown-option {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-dropdown-option);\n      }\n    }\n  }\n  .hover\\:bg-full-dropdown-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-full-dropdown-hover);\n      }\n    }\n  }\n  .hover\\:bg-primary-hover {\n    &:hover {\n      @media (hover: hover) {\n        background-color: var(--color-primary-hover);\n      }\n    }\n  }\n  .hover\\:\\!text-red-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-red-button-hover) !important;\n      }\n    }\n  }\n  .hover\\:text-blue-800 {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-blue-800);\n      }\n    }\n  }\n  .hover\\:text-nav-link-hover {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-nav-link-hover);\n      }\n    }\n  }\n  .hover\\:text-primary {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-primary);\n      }\n    }\n  }\n  .hover\\:text-primary-hover {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-primary-hover);\n      }\n    }\n  }\n  .hover\\:text-red-button {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-red-button);\n      }\n    }\n  }\n  .hover\\:text-red-button-hover {\n    &:hover {\n      @media (hover: hover) {\n        color: var(--color-red-button-hover);\n      }\n    }\n  }\n  .hover\\:no-underline {\n    &:hover {\n      @media (hover: hover) {\n        text-decoration-line: none;\n      }\n    }\n  }\n  .hover\\:outline-add-outline-hover {\n    &:hover {\n      @media (hover: hover) {\n        outline-color: var(--color-add-outline-hover);\n      }\n    }\n  }\n  .focus\\:outline-2 {\n    &:focus {\n      outline-style: var(--tw-outline-style);\n      outline-width: 2px;\n    }\n  }\n  .data-\\[active\\=False\\]\\:translate-y-\\[500\\%\\] {\n    &[data-active=\"False\"] {\n      --tw-translate-y: 500%;\n      translate: var(--tw-translate-x) var(--tw-translate-y);\n    }\n  }\n  .data-\\[active\\=True\\]\\:border-card-header-highlight {\n    &[data-active=\"True\"] {\n      border-color: var(--color-card-header-highlight);\n    }\n  }\n  .data-\\[active\\=True\\]\\:bg-backdrop\\/40 {\n    &[data-active=\"True\"] {\n      background-color: color-mix(in srgb, oklch(0.446 0.03 256.802) 40%, transparent);\n      @supports (color: color-mix(in lab, red, red)) {\n        background-color: color-mix(in oklab, var(--color-backdrop) 40%, transparent);\n      }\n    }\n  }\n  .data-\\[active\\=True\\]\\:bg-modal\\/100 {\n    &[data-active=\"True\"] {\n      background-color: var(--color-modal);\n    }\n  }\n  .data-\\[coloring\\=Default\\]\\:mx-\\[-0\\.25rem\\] {\n    &[data-coloring=\"Default\"] {\n      margin-inline: -0.25rem;\n    }\n  }\n  .data-\\[coloring\\=Default\\]\\:text-card-data-points {\n    &[data-coloring=\"Default\"] {\n      color: var(--color-card-data-points);\n    }\n  }\n  .data-\\[coloring\\=Green\\]\\:bg-green-500 {\n    &[data-coloring=\"Green\"] {\n      background-color: var(--color-green-500);\n    }\n  }\n  .data-\\[coloring\\=Red\\]\\:bg-red-500 {\n    &[data-coloring=\"Red\"] {\n      background-color: var(--color-red-500);\n    }\n  }\n  .data-\\[coloring\\=Yellow\\]\\:bg-yellow-500 {\n    &[data-coloring=\"Yellow\"] {\n      background-color: var(--color-yellow-500);\n    }\n  }\n  .\\32 xs\\:flex {\n    @media (width >= 20rem) {\n      display: flex;\n    }\n  }\n  .sm\\:\\!hidden {\n    @media (width >= 40rem) {\n      display: none !important;\n    }\n  }\n  .sm\\:block {\n    @media (width >= 40rem) {\n      display: block;\n    }\n  }\n  .sm\\:gap-5 {\n    @media (width >= 40rem) {\n      gap: calc(var(--spacing) * 5);\n    }\n  }\n  .sm\\:px-12 {\n    @media (width >= 40rem) {\n      padding-inline: calc(var(--spacing) * 12);\n    }\n  }\n  .md\\:flex {\n    @media (width >= 48rem) {\n      display: flex;\n    }\n  }\n  .md\\:w-64 {\n    @media (width >= 48rem) {\n      width: calc(var(--spacing) * 64);\n    }\n  }\n  .md\\:w-80 {\n    @media (width >= 48rem) {\n      width: calc(var(--spacing) * 80);\n    }\n  }\n  .md\\:max-w-3xl {\n    @media (width >= 48rem) {\n      max-width: var(--container-3xl);\n    }\n  }\n  .md\\:flex-row {\n    @media (width >= 48rem) {\n      flex-direction: row;\n    }\n  }\n  .md\\:text-xl {\n    @media (width >= 48rem) {\n      font-size: var(--text-xl);\n      line-height: var(--tw-leading, var(--text-xl--line-height));\n    }\n  }\n  .lg\\:flex {\n    @media (width >= 64rem) {\n      display: flex;\n    }\n  }\n  .lg\\:hidden {\n    @media (width >= 64rem) {\n      display: none;\n    }\n  }\n}\n@layer base {\n  [data-theme='dark'] {\n    --color-primary: oklch(0.595 0.2538 297);\n    --color-primary-hover: oklch(0.700 0.280 297);\n    --color-card-bg: oklch(0.25 0.005 247.896);\n    --color-card-diff-bg: oklch(0.32 0.005 48.717);\n    --color-card-blocked-bg: oklch(0.258 0.092 26.042);\n    --color-card-blocked-text: oklch(0.808 0.114 19.571);\n    --color-add-outline: oklch(0.8 0.027 264.364);\n    --color-add-outline-hover: oklch(0.95 0.034 264.665);\n    --color-column-limit-reached: oklch(0.258 0.092 26.042);\n    --color-cancel-button: oklch(0.45 0.027 264.364);\n    --color-cancel-button-hover: oklch(0.60 0.034 259.733);\n    --color-red-button: oklch(0.637 0.237 25.331);\n    --color-red-button-hover: oklch(0.700 0.250 25.331);\n    --color-green-button: oklch(0.527 0.154 150.069);\n    --color-green-button-hover: oklch(0.723 0.219 149.579);\n    --color-backdrop: oklch(0.1 0.01 256.802);\n    --color-modal: oklch(0.20 0.01 247.896);\n    --color-dropdown-option: oklch(0.35 0.01 258.338);\n    --color-icon: oklch(0.65 0.027 264.364);\n    --color-icon-hover: oklch(0.85 0.034 264.665);\n    --color-icon-bg-hover: oklch(0.4 0.01 252.894);\n    --color-card-icon-bg-hover: oklch(0.4 0.005 247.896);\n    --color-disabled-icon: oklch(0.50 0.027 264.364);\n    --color-label-text: #fff;\n    --color-card-data-points: oklch(0.70 0.027 264.364);\n    --color-search-bar: oklch(0.22 0.01 255.508);\n    --color-full-dropdown: oklch(0.22 0.01 255.508);\n    --color-full-dropdown-hover: oklch(0.35 0.01 255.508);\n    --color-full-dropdown-disabled: oklch(0.33 0.01 255.508);\n    --color-typing-outline: oklch(0.65 0.105 251.813);\n    --color-card-heading: oklch(0.50 0.01 56.259);\n    --color-auth-bottom-text: oklch(0.55 0.022 261.325);\n    --color-auth-bg: oklch(0.15 0.01 247.896);\n    --color-tab-outline: oklch(0.55 0.022 261.325);\n    --color-nav-link: oklch(0.85 0.04 257.417);\n    --color-nav-link-hover: oklch(0.8 0.2538 297);\n    --color-avatar-ring: oklch(0.90 0.01 250);\n    --color-app-bg: oklch(0.12 0.01 252.894);\n    --color-button-text: oklch(0.968 0.007 247.896);\n    --color-app-text: oklch(0.95 0.01 250);\n    --color-card-heading: #fff;\n    --color-auth-gradient-start: oklch(0.277 0.046 192.524);\n    --color-auth-gradient-via: oklch(0.291 0.149 302.717);\n    --color-auth-gradient-to: oklch(0.284 0.109 3.907);\n    --color-checkbox-bg: oklch(0.12 0.01 252.894);\n    --color-divide: oklch(0.45 0.006 264.531);\n    --color-card-header-highlight: #fff;\n    --color-card-edit-label: oklch(0.95 0.01 250);\n    --color-person-label-bg: oklch(0.20 0.01 247.896);\n    --color-scrollbar-track: oklch(0.15 0.005 250);\n    --color-scrollbar-thumb: oklch(0.50 0.01 250);\n    --color-scrollbar-thumb-hover: oklch(0.65 0.015 250);\n  }\n  *, ::after, ::before, ::backdrop, ::file-selector-button {\n    border-color: var(--color-divide, currentColor);\n  }\n}\ninput[type=\"checkbox\"]:not(.switch) {\n  height: calc(var(--spacing) * 4);\n  width: calc(var(--spacing) * 4);\n  min-width: calc(var(--spacing) * 4);\n  cursor: pointer;\n  appearance: none;\n  border-radius: var(--radius-sm);\n  border-style: var(--tw-border-style);\n  border-width: 1px;\n  border-color: var(--color-add-outline);\n  background-color: var(--color-card-bg);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n}\ninput[type=\"checkbox\"]:not(.switch):checked {\n  background-color: var(--color-primary);\n  background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\");\n}\noption {\n  background-color: var(--color-modal);\n}\nhtml[data-theme='dark'] {\n  color-scheme: dark;\n}\n[data-theme='dark'] body {\n  color-scheme: dark;\n}\n[data-theme='dark'] ::-webkit-scrollbar-track {\n  background: var(--color-scrollbar-track);\n  border-radius: 10px;\n}\n[data-theme='dark'] ::-webkit-scrollbar-thumb {\n  background: var(--color-scrollbar-thumb);\n  border-radius: 10px;\n  border: 3px solid var(--color-scrollbar-track);\n}\n[data-theme='dark'] ::-webkit-scrollbar-thumb:hover {\n  background: var(--color-scrollbar-thumb-hover);\n}\n[data-theme='dark'] html {\n  scrollbar-width: thin;\n  scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);\n}\nh1:focus {\n  outline: none;\n}\nbody, input {\n  font-family: 'Noto Sans';\n}\ninput {\n  outline: none;\n}\n.nav-links {\n  display: flex;\n  flex-direction: row;\n  gap: calc(var(--spacing) * 10);\n  align-self: center;\n  color: var(--color-nav-link);\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  --tw-tracking: var(--tracking-wide);\n  letter-spacing: var(--tracking-wide);\n}\n.nav-link {\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  -webkit-user-select: none;\n  user-select: none;\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-nav-link-hover);\n    }\n  }\n  cursor: pointer;\n  z-index: 10;\n}\n.active {\n  color: var(--color-nav-link-hover);\n}\n.avatar {\n  width: calc(var(--spacing) * 8);\n  min-width: calc(var(--spacing) * 8);\n  height: calc(var(--spacing) * 8);\n  min-height: calc(var(--spacing) * 8);\n  background-position: center;\n  background-size: cover;\n  border-radius: 50%;\n  cursor: pointer;\n}\n.stack-avatars {\n  margin-left: -1rem;\n  outline-style: var(--tw-outline-style);\n  outline-width: 1px;\n  outline-color: var(--color-avatar-ring);\n}\n.avatar-border {\n  --tw-shadow: 0 0 2px 2px var(--tw-shadow-color, currentcolor);\n  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  --tw-shadow-color: oklch(0.595 0.2538 297);\n  @supports (color: color-mix(in lab, red, red)) {\n    --tw-shadow-color: color-mix(in oklab, var(--color-primary) var(--tw-shadow-alpha), transparent);\n  }\n}\n.max-h-visible-screen {\n  max-height: calc(var(--vvh) * 100 - (var(--spacing) * 6) - (var(--spacing) * 2) * 6 - (var(--spacing) * 8) * 2 - 17px);\n}\n.h-board-content {\n  height: calc(var(--vvh) * 100 - (var(--spacing) * 6) * 4 - 1px);\n}\n.h-visible-screen {\n  height: calc(var(--vvh) * 100);\n}\n.board-column {\n  display: flex;\n  width: calc(var(--spacing) * 64);\n  flex-direction: column;\n  align-items: center;\n}\n.task-card {\n  margin-bottom: calc(var(--spacing) * 2);\n  display: flex;\n  width: 100%;\n  cursor: pointer;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 3);\n  border-radius: var(--radius-lg);\n  background-color: var(--color-card-bg);\n  padding: calc(var(--spacing) * 3);\n  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  -webkit-user-select: none;\n  user-select: none;\n  &[data-blocked=\"True\"] {\n    background-color: var(--color-card-blocked-bg);\n  }\n}\n.to-task-card {\n  -webkit-user-select: none;\n  user-select: none;\n  &[data-active=\"True\"] {\n    display: flex;\n  }\n  &[data-active=\"True\"] {\n    flex-direction: column;\n  }\n  &[data-active=\"True\"] {\n    gap: calc(var(--spacing) * 3);\n  }\n  &[data-active=\"True\"] {\n    background-color: var(--color-card-bg);\n  }\n  &[data-active=\"True\"] {\n    padding: calc(var(--spacing) * 3);\n  }\n  &[data-active=\"True\"] {\n    --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n    box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  }\n  &[data-active=\"True\"] {\n    outline-style: var(--tw-outline-style);\n    outline-width: 0px;\n  }\n}\n.priority {\n  width: fit-content;\n  cursor: pointer;\n  border-radius: var(--radius-lg);\n  padding-inline: calc(var(--spacing) * 3);\n  padding-block: calc(var(--spacing) * 1);\n  font-size: var(--text-2xs);\n  --tw-font-weight: var(--font-weight-bold);\n  font-weight: var(--font-weight-bold);\n}\n.label {\n  display: flex;\n  width: fit-content;\n  cursor: pointer;\n  align-items: center;\n  justify-content: center;\n  border-radius: var(--radius-lg);\n  padding-inline: calc(var(--spacing) * 3);\n  padding-block: calc(var(--spacing) * 1);\n  font-size: var(--text-2xs);\n  --tw-font-weight: var(--font-weight-bold);\n  font-weight: var(--font-weight-bold);\n}\n.card-data-point {\n  display: flex;\n  cursor: pointer;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  gap: calc(var(--spacing) * 1);\n  white-space: nowrap;\n}\nbutton, button[type='submit'], .label-as-button {\n  border-radius: var(--radius-lg);\n  background-color: var(--color-primary);\n  padding-block: calc(var(--spacing) * 2);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  color: var(--color-button-text);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-primary-hover);\n    }\n  }\n}\nbutton, .label-as-button > label {\n  cursor: pointer;\n}\nbutton, .label-as-button > i {\n  cursor: pointer;\n}\n::-webkit-scrollbar {\n  height: calc(var(--spacing) * 2);\n  width: calc(var(--spacing) * 2);\n}\n::-webkit-scrollbar-track {\n  background: #f1f1f1;\n}\n::-webkit-scrollbar-thumb {\n  background: #888;\n  border-radius: 8px;\n}\n::-webkit-scrollbar-thumb:hover {\n  background: #555;\n}\n.auth-bg {\n  display: flex;\n  height: 100%;\n  width: 100%;\n  align-items: center;\n  justify-content: center;\n  --tw-gradient-position: to top right in oklab;\n  background-image: linear-gradient(var(--tw-gradient-stops));\n  --tw-gradient-from: var(--color-auth-gradient-start);\n  --tw-gradient-via: var(--color-auth-gradient-via);\n  --tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);\n  --tw-gradient-stops: var(--tw-gradient-via-stops);\n  --tw-gradient-to: var(--color-auth-gradient-to);\n  --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n}\n.auth-inp-label {\n  display: flex;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 2);\n}\n.auth-label {\n  margin-left: calc(var(--spacing) * 1);\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  --tw-font-weight: var(--font-weight-semibold);\n  font-weight: var(--font-weight-semibold);\n  opacity: 80%;\n}\n.auth-input {\n  height: calc(var(--spacing) * 8);\n  width: 100%;\n  border-bottom-style: var(--tw-border-style);\n  border-bottom-width: 2px;\n  border-color: var(--color-gray-600);\n  background-color: var(--color-auth-bg);\n  padding-inline: calc(var(--spacing) * 2);\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  --tw-font-weight: var(--font-weight-normal);\n  font-weight: var(--font-weight-normal);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:focus {\n    border-color: var(--color-primary);\n  }\n}\n.auth-button {\n  margin-top: calc(var(--spacing) * 5);\n  border-radius: calc(infinity * 1px) !important;\n  font-size: var(--text-base) !important;\n  line-height: var(--tw-leading, var(--text-base--line-height)) !important;\n}\n.auth-card {\n  margin-inline: calc(var(--spacing) * 2);\n  display: flex;\n  width: 30rem;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 12);\n  border-radius: var(--radius-lg);\n  background-color: var(--color-auth-bg);\n  padding-inline: calc(var(--spacing) * 12);\n  padding-block: calc(var(--spacing) * 24);\n  --tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));\n  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n}\n.auth-form {\n  display: flex;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 6);\n}\n.auth-link {\n  cursor: pointer;\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  --tw-font-weight: var(--font-weight-semibold);\n  font-weight: var(--font-weight-semibold);\n  color: var(--color-primary);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-primary-hover);\n    }\n  }\n}\ninput[type=\"checkbox\"].switch {\n  font-size: 30px;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  width: 3.5em;\n  height: 1.5em;\n  background: transparent;\n  border-radius: 3em;\n  position: relative;\n  cursor: pointer;\n  -webkit-transition: all .2s ease-in-out;\n  transition: all .2s ease-in-out;\n  --tw-scale-x: 50%;\n  --tw-scale-y: 50%;\n  --tw-scale-z: 50%;\n  scale: var(--tw-scale-x) var(--tw-scale-y);\n  background-color: var(--color-checkbox-bg);\n  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n}\n[data-theme='dark'] input[type=\"checkbox\"].switch {\n  outline-style: var(--tw-outline-style);\n  outline-width: 3px;\n}\ninput[type=\"checkbox\"].switch:checked {\n  background-color: var(--color-primary);\n}\ninput[type=\"checkbox\"].switch:after {\n  position: absolute;\n  content: \"\";\n  width: 1.5em;\n  height: 1.5em;\n  border-radius: 50%;\n  background: #fff;\n  -webkit-transform: scale(.7);\n  transform: scale(.7);\n  left: 0;\n  -webkit-transition: all .2s ease-in-out;\n  transition: all .2s ease-in-out;\n}\ninput[type=\"checkbox\"].switch:checked:after {\n  left: calc(100% - 1.5em);\n}\n.settings-menu-item {\n  cursor: pointer;\n  border-radius: var(--radius-lg);\n  padding-inline: calc(var(--spacing) * 2);\n  padding-block: calc(var(--spacing) * 1);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  -webkit-user-select: none;\n  user-select: none;\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-slate-400);\n    }\n  }\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-app-text);\n    }\n  }\n  &[data-active=\"true\"] {\n    background-color: color-mix(in srgb, oklch(0.381 0.176 304.987) 20%, transparent);\n    @supports (color: color-mix(in lab, red, red)) {\n      background-color: color-mix(in oklab, var(--color-primary-hover) 20%, transparent);\n    }\n  }\n  &[data-active=\"true\"] {\n    color: var(--color-primary-hover);\n  }\n}\n.settings-item {\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  gap: calc(var(--spacing) * 2);\n  padding-block: calc(var(--spacing) * 5);\n  @media (width >= 64rem) {\n    flex-direction: row;\n  }\n  @media (width >= 64rem) {\n    align-items: center;\n  }\n}\n.board-card-create {\n  display: flex;\n  cursor: pointer;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  gap: calc(var(--spacing) * 5);\n  color: var(--color-add-outline);\n  outline-style: var(--tw-outline-style);\n  outline-width: 1px;\n  outline-color: var(--color-add-outline);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  --tw-outline-style: dashed;\n  outline-style: dashed;\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-add-outline-hover);\n    }\n  }\n  &:hover {\n    @media (hover: hover) {\n      outline-color: var(--color-add-outline-hover);\n    }\n  }\n  height: min-content;\n  width: 100%;\n  border-radius: var(--radius-lg);\n  padding-inline: calc(var(--spacing) * 5);\n  padding-block: calc(var(--spacing) * 5);\n  -webkit-user-select: none;\n  user-select: none;\n  @media (width >= 40rem) {\n    width: calc(var(--spacing) * 72);\n  }\n}\n.add label {\n  cursor: pointer;\n}\n.card-button {\n  cursor: pointer;\n  border-radius: var(--radius-lg);\n  background-color: transparent;\n  padding: calc(var(--spacing) * 1);\n  color: var(--color-add-outline);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-icon-bg-hover);\n    }\n  }\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-add-outline-hover);\n    }\n  }\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-card-icon-bg-hover) !important;\n    }\n  }\n}\n.board-card {\n  display: flex;\n  height: min-content;\n  width: 100%;\n  cursor: pointer;\n  flex-direction: column;\n  border-radius: var(--radius-lg);\n  background-color: var(--color-card-bg);\n  padding-inline: calc(var(--spacing) * 5);\n  padding-block: calc(var(--spacing) * 5);\n  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  -webkit-user-select: none;\n  user-select: none;\n  &:hover {\n    @media (hover: hover) {\n      --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n      box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n    }\n  }\n  @media (width >= 40rem) {\n    width: calc(var(--spacing) * 72);\n  }\n}\n[data-theme=''] .board-card {\n  &:hover {\n    @media (hover: hover) {\n      --tw-shadow-color: oklch(55.1% 0.027 264.364);\n      @supports (color: color-mix(in lab, red, red)) {\n        --tw-shadow-color: color-mix(in oklab, var(--color-gray-500) var(--tw-shadow-alpha), transparent);\n      }\n    }\n  }\n}\n[data-theme='dark'] .board-card {\n  &:hover {\n    @media (hover: hover) {\n      outline-style: var(--tw-outline-style);\n      outline-width: 1px;\n    }\n  }\n}\n.board-card-data-point {\n  display: flex;\n  cursor: pointer;\n  flex-direction: row;\n  align-items: center;\n  justify-content: flex-start;\n  gap: calc(var(--spacing) * 3);\n  padding-left: calc(var(--spacing) * 1);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  color: var(--color-card-data-points);\n}\n.board-card-data-point > i {\n  width: calc(var(--spacing) * 4);\n  font-size: var(--text-base);\n  line-height: var(--tw-leading, var(--text-base--line-height));\n}\n.field-validation-error, .validation-message {\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  color: var(--color-red-button);\n}\n.form {\n  display: flex;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 3);\n}\n.form-group {\n  display: flex;\n  flex-direction: column;\n  gap: calc(var(--spacing) * 1);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n}\n.form-group > label {\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  --tw-font-weight: var(--font-weight-light);\n  font-weight: var(--font-weight-light);\n}\n.form-group > .form-control {\n  border-bottom-style: var(--tw-border-style);\n  border-bottom-width: 2px;\n  border-color: var(--color-purple-300);\n  padding-inline: calc(var(--spacing) * 2);\n  padding-block: calc(var(--spacing) * 1);\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  &:focus {\n    border-color: var(--color-primary);\n  }\n}\n.dragging {\n  rotate: 6deg;\n  transition-property: transform, translate, scale, rotate;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n}\n.edit-task-label {\n  width: calc(var(--spacing) * 24);\n  overflow: hidden;\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  --tw-font-weight: var(--font-weight-normal);\n  font-weight: var(--font-weight-normal);\n  color: var(--color-card-edit-label);\n}\n.edit-task-item {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: calc(var(--spacing) * 2);\n  font-size: var(--text-sm);\n  line-height: var(--tw-leading, var(--text-sm--line-height));\n  --tw-font-weight: var(--font-weight-medium);\n  font-weight: var(--font-weight-medium);\n}\n.person-label {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  gap: calc(var(--spacing) * 1);\n  overflow: hidden;\n  border-radius: calc(infinity * 1px);\n  background-color: var(--color-person-label-bg);\n  padding: calc(var(--spacing) * 1);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  --tw-font-weight: var(--font-weight-normal);\n  font-weight: var(--font-weight-normal);\n}\n[data-theme='dark'] .person-label, [data-theme='dark'] .card-label {\n  outline-style: var(--tw-outline-style);\n  outline-width: 2px;\n}\n.person-label > div {\n  width: calc(var(--spacing) * 5);\n  height: calc(var(--spacing) * 5);\n  background-position: center;\n  background-size: cover;\n  border-radius: 50%;\n}\n.card-label {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  gap: calc(var(--spacing) * 2);\n  overflow: hidden;\n  border-radius: calc(infinity * 1px);\n  background-color: var(--color-person-label-bg);\n  padding-inline: calc(var(--spacing) * 2);\n  padding-block: calc(var(--spacing) * 1.5);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  --tw-font-weight: var(--font-weight-normal);\n  font-weight: var(--font-weight-normal);\n}\n.edit-icon {\n  cursor: pointer;\n  padding: calc(var(--spacing) * 2);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  color: var(--color-add-outline);\n  outline-color: var(--color-add-outline);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:hover {\n    @media (hover: hover) {\n      color: var(--color-add-outline-hover);\n    }\n  }\n  &:hover {\n    @media (hover: hover) {\n      outline-color: var(--color-add-outline-hover);\n    }\n  }\n}\n.icon {\n  padding: calc(var(--spacing) * 2);\n  font-size: var(--text-xs);\n  line-height: var(--tw-leading, var(--text-xs--line-height));\n  color: var(--color-add-outline);\n  outline-color: var(--color-add-outline);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n}\n.priority-selector-item {\n  display: flex;\n  cursor: pointer;\n  flex-direction: row;\n  align-items: center;\n  justify-content: space-between;\n  padding-inline: calc(var(--spacing) * 2);\n  padding-block: calc(var(--spacing) * 2);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-dropdown-option);\n    }\n  }\n}\n.person-link {\n  cursor: pointer;\n  align-items: stretch;\n  border-radius: var(--radius-lg);\n  background-color: var(--color-blue-600);\n  padding-inline: calc(var(--spacing) * 1);\n  padding-bottom: calc(var(--spacing) * 0.5);\n  white-space: pre-wrap;\n  color: var(--color-white);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n  --tw-ease: var(--ease-in-out);\n  transition-timing-function: var(--ease-in-out);\n  &:hover {\n    @media (hover: hover) {\n      background-color: var(--color-blue-700);\n    }\n  }\n}\n.plk-dd-spacing {\n  height: calc(var(--spacing) * 1);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n}\n.plk-dd-spacing-dragged-over {\n  height: calc(var(--spacing) * 24);\n  transition-property: all;\n  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n  transition-duration: var(--tw-duration, var(--default-transition-duration));\n}\n.plk-dd-inprogess > * {\n  pointer-events: none;\n}\n.element-spinner {\n  border-radius: 50%;\n  animation: spin 1s ease-in-out infinite;\n  height: calc(var(--spacing) * 10);\n  width: calc(var(--spacing) * 10);\n  border-style: var(--tw-border-style);\n  border-width: 4px;\n  border-color: var(--color-card-bg);\n  border-top-color: var(--color-primary);\n  &[data-small=\"True\"] {\n    height: calc(var(--spacing) * 5);\n  }\n  &[data-small=\"True\"] {\n    width: calc(var(--spacing) * 5);\n  }\n}\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n.element-spinner-wrapper {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  width: 100%;\n  height: 100%;\n}\n.valid.modified:not([type=checkbox]) {\n  outline: 1px solid #26b050;\n}\n.invalid {\n  outline: 1px solid #e50000;\n}\n.blazor-error-boundary {\n  background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;\n  padding: 1rem 1rem 1rem 3.7rem;\n  color: white;\n}\n.blazor-error-boundary::after {\n  content: \"An error has occurred.\";\n}\n#blazor-error-ui {\n  color-scheme: light only;\n  background: lightyellow;\n  bottom: 0;\n  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);\n  box-sizing: border-box;\n  display: none;\n  left: 0;\n  padding: 0.6rem 1.25rem 0.7rem 1.25rem;\n  position: fixed;\n  width: 100%;\n  z-index: 1000;\n}\n#blazor-error-ui .dismiss {\n  cursor: pointer;\n  position: absolute;\n  right: 0.75rem;\n  top: 0.5rem;\n}\n.tooltip-wrapper {\n  position: relative;\n  display: inline-block;\n  cursor: help;\n}\n.tooltip-span {\n  visibility: hidden;\n  position: absolute;\n  width: 120px;\n  bottom: 100%;\n  left: 50%;\n  margin-left: -60px;\n  background-color: #363636;\n  color: #fff;\n  text-align: center;\n  padding: 5px 0;\n  border-radius: 6px;\n  z-index: 1;\n}\n.tooltip-span::after {\n  content: \"\";\n  position: absolute;\n  top: 100%;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px;\n  border-style: solid;\n  border-color: #555 transparent transparent transparent;\n}\n.tooltip-wrapper:hover .tooltip-span {\n  visibility: visible;\n}\n.sortable-chosen {\n  animation: var(--animate-pulse);\n}\n[data-theme='dark'] .task-card.sortable-chosen {\n  border-style: var(--tw-border-style);\n  border-width: 2px;\n}\n.dropdown-animate {\n  transition: opacity 0.1s cubic-bezier(0.4,0,0.2,1), transform 0.1s cubic-bezier(0.4,0,0.2,1);\n  transform: translateY(-10px);\n  opacity: 0;\n}\n.dropdown-animate-in {\n  transform: translateY(0);\n  opacity: 1;\n}\n@property --tw-outline-style {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: solid;\n}\n@property --tw-ease {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-border-spacing-x {\n  syntax: \"<length>\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-border-spacing-y {\n  syntax: \"<length>\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-rotate-x {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-rotate-y {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-rotate-z {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-skew-x {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-skew-y {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-divide-x-reverse {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-border-style {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: solid;\n}\n@property --tw-divide-y-reverse {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-font-weight {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-shadow {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-shadow-alpha {\n  syntax: \"<percentage>\";\n  inherits: false;\n  initial-value: 100%;\n}\n@property --tw-inset-shadow {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n  syntax: \"<percentage>\";\n  inherits: false;\n  initial-value: 100%;\n}\n@property --tw-ring-color {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-ring-shadow {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-inset-ring-shadow {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-ring-offset-width {\n  syntax: \"<length>\";\n  inherits: false;\n  initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0 0 #0000;\n}\n@property --tw-blur {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-brightness {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-contrast {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-grayscale {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-hue-rotate {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-invert {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-opacity {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-saturate {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-sepia {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-drop-shadow {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-drop-shadow-color {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-drop-shadow-alpha {\n  syntax: \"<percentage>\";\n  inherits: false;\n  initial-value: 100%;\n}\n@property --tw-drop-shadow-size {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-translate-x {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-translate-y {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-translate-z {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 0;\n}\n@property --tw-tracking {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-gradient-position {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-gradient-from {\n  syntax: \"<color>\";\n  inherits: false;\n  initial-value: #0000;\n}\n@property --tw-gradient-via {\n  syntax: \"<color>\";\n  inherits: false;\n  initial-value: #0000;\n}\n@property --tw-gradient-to {\n  syntax: \"<color>\";\n  inherits: false;\n  initial-value: #0000;\n}\n@property --tw-gradient-stops {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-gradient-via-stops {\n  syntax: \"*\";\n  inherits: false;\n}\n@property --tw-gradient-from-position {\n  syntax: \"<length-percentage>\";\n  inherits: false;\n  initial-value: 0%;\n}\n@property --tw-gradient-via-position {\n  syntax: \"<length-percentage>\";\n  inherits: false;\n  initial-value: 50%;\n}\n@property --tw-gradient-to-position {\n  syntax: \"<length-percentage>\";\n  inherits: false;\n  initial-value: 100%;\n}\n@property --tw-scale-x {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 1;\n}\n@property --tw-scale-y {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 1;\n}\n@property --tw-scale-z {\n  syntax: \"*\";\n  inherits: false;\n  initial-value: 1;\n}\n@keyframes spin {\n  to {\n    transform: rotate(360deg);\n  }\n}\n@keyframes pulse {\n  50% {\n    opacity: 0.5;\n  }\n}\n@layer properties {\n  @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n    *, ::before, ::after, ::backdrop {\n      --tw-outline-style: solid;\n      --tw-ease: initial;\n      --tw-border-spacing-x: 0;\n      --tw-border-spacing-y: 0;\n      --tw-rotate-x: initial;\n      --tw-rotate-y: initial;\n      --tw-rotate-z: initial;\n      --tw-skew-x: initial;\n      --tw-skew-y: initial;\n      --tw-divide-x-reverse: 0;\n      --tw-border-style: solid;\n      --tw-divide-y-reverse: 0;\n      --tw-font-weight: initial;\n      --tw-shadow: 0 0 #0000;\n      --tw-shadow-color: initial;\n      --tw-shadow-alpha: 100%;\n      --tw-inset-shadow: 0 0 #0000;\n      --tw-inset-shadow-color: initial;\n      --tw-inset-shadow-alpha: 100%;\n      --tw-ring-color: initial;\n      --tw-ring-shadow: 0 0 #0000;\n      --tw-inset-ring-color: initial;\n      --tw-inset-ring-shadow: 0 0 #0000;\n      --tw-ring-inset: initial;\n      --tw-ring-offset-width: 0px;\n      --tw-ring-offset-color: #fff;\n      --tw-ring-offset-shadow: 0 0 #0000;\n      --tw-blur: initial;\n      --tw-brightness: initial;\n      --tw-contrast: initial;\n      --tw-grayscale: initial;\n      --tw-hue-rotate: initial;\n      --tw-invert: initial;\n      --tw-opacity: initial;\n      --tw-saturate: initial;\n      --tw-sepia: initial;\n      --tw-drop-shadow: initial;\n      --tw-drop-shadow-color: initial;\n      --tw-drop-shadow-alpha: 100%;\n      --tw-drop-shadow-size: initial;\n      --tw-translate-x: 0;\n      --tw-translate-y: 0;\n      --tw-translate-z: 0;\n      --tw-tracking: initial;\n      --tw-gradient-position: initial;\n      --tw-gradient-from: #0000;\n      --tw-gradient-via: #0000;\n      --tw-gradient-to: #0000;\n      --tw-gradient-stops: initial;\n      --tw-gradient-via-stops: initial;\n      --tw-gradient-from-position: 0%;\n      --tw-gradient-via-position: 50%;\n      --tw-gradient-to-position: 100%;\n      --tw-scale-x: 1;\n      --tw-scale-y: 1;\n      --tw-scale-z: 1;\n    }\n  }\n}\n"
  },
  {
    "path": "Ticky.Web/wwwroot/emails/DeadlineReminder.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Deadline Today: {CARD_CODE}</title>\n    <style>\n      body {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n          Oxygen, Ubuntu, Cantarell, sans-serif;\n        line-height: 1.5;\n        color: #374151;\n        margin: 0;\n        padding: 20px;\n        background-color: #f1f5f9;\n      }\n      .container {\n        background-color: white;\n        border-radius: 12px;\n        padding: 32px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n          0 2px 4px -1px rgba(0, 0, 0, 0.06);\n        border: 1px solid #e2e8f0;\n        max-width: 420px;\n        margin: 0 auto;\n      }\n      .header {\n        text-align: center;\n        margin-bottom: 32px;\n        padding-bottom: 24px;\n        border-bottom: 1px solid #e2e8f0;\n      }\n      .card-code {\n        display: inline-block;\n        background-color: #dbeafe;\n        color: #1e40af;\n        padding: 6px 12px;\n        border-radius: 6px;\n        font-family: \"SF Mono\", Monaco, \"Cascadia Code\", \"Roboto Mono\", Consolas,\n          \"Courier New\", monospace;\n        font-weight: 600;\n        font-size: 14px;\n        margin-bottom: 12px;\n      }\n      .card-title {\n        font-size: 22px;\n        font-weight: 600;\n        margin: 0;\n        color: #1f2937;\n      }\n      .deadline-section {\n        background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);\n        border: 1px solid #dc2626;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 24px 0;\n        text-align: center;\n      }\n      .deadline-icon {\n        font-size: 24px;\n        margin-bottom: 8px;\n      }\n      .deadline-text {\n        font-weight: 600;\n        color: #dc2626;\n        margin: 0;\n      }\n      .content-section {\n        background-color: #f8fafc;\n        border: 1px solid #e2e8f0;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 20px 0;\n      }\n      .section-title {\n        font-size: 16px;\n        font-weight: 600;\n        color: #374151;\n        margin: 0 0 12px 0;\n        display: flex;\n        align-items: center;\n      }\n      .section-title span {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 16px;\n        line-height: 1;\n        margin-right: 4px;\n      }\n      .description-text {\n        color: #6b7280;\n        margin: 0;\n        line-height: 1.6;\n      }\n      .subtasks-list {\n        margin: 0;\n        padding-left: 0;\n        list-style: none;\n      }\n      .subtasks-list .subtask-item {\n        margin-bottom: 4px;\n      }\n      .subtasks-list .subtask-item:last-child {\n        margin-bottom: 0;\n      }\n      .subtask-item {\n        display: flex;\n        align-items: center;\n        padding: 10px 0;\n        border-bottom: 1px solid #e5e7eb;\n      }\n      .subtask-item span:first-child {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 14px;\n        line-height: 1;\n        flex-shrink: 0;\n        margin-right: 4px;\n      }\n      .subtask-item:last-child {\n        border-bottom: none;\n      }\n      .subtask-completed {\n        text-decoration: line-through;\n        color: #9ca3af;\n      }\n      .cta-section {\n        text-align: center;\n        margin: 32px 0;\n      }\n      .cta-button {\n        display: inline-block;\n        background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);\n        color: #ffffff !important;\n        padding: 14px 28px;\n        text-decoration: none;\n        border-radius: 8px;\n        font-weight: 600;\n        font-size: 16px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n        transition: all 0.2s;\n        border: 2px solid #991b1b;\n      }\n      .cta-button:hover {\n        background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);\n        transform: translateY(-1px);\n        box-shadow: 0 6px 8px -1px rgba(0, 0, 0, 0.15);\n        color: #ffffff !important;\n      }\n      .footer {\n        margin-top: 32px;\n        padding-top: 24px;\n        border-top: 1px solid #e2e8f0;\n        font-size: 14px;\n        color: #6b7280;\n        text-align: center;\n      }\n      .footer p {\n        margin: 8px 0;\n      }\n      .tip-box {\n        background-color: #eff6ff;\n        border: 1px solid #bfdbfe;\n        border-radius: 6px;\n        padding: 12px;\n        margin: 16px 0;\n      }\n\n      @media screen and (max-width: 400px) {\n        body {\n          padding: 16px;\n        }\n        .container {\n          padding: 24px;\n        }\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"header\">\n        <img\n          src=\"https://raw.githubusercontent.com/dkorecko/Ticky/refs/heads/main/Ticky.Web/wwwroot/images/ticky.png\"\n          alt=\"Ticky\"\n          style=\"\n            height: 40px;\n            margin-bottom: 8px;\n            display: block;\n            margin-left: auto;\n            margin-right: auto;\n          \"\n        />\n        <div class=\"card-code\">{CARD_CODE}</div>\n        <h1 class=\"card-title\">{CARD_TEXT}</h1>\n      </div>\n\n      <div class=\"deadline-section\">\n        <div class=\"deadline-icon\">🚨</div>\n        <p class=\"deadline-text\">Deadline is TODAY at {CARD_SCHEDULED_FOR}</p>\n      </div>\n\n      {CARD_DESCRIPTION_SECTION}\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📝</span>\n          Description\n        </h3>\n        <p class=\"description-text\">{CARD_DESCRIPTION}</p>\n      </div>\n      {CARD_DESCRIPTION_SECTION} {CARD_SUBTASKS_SECTION}\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📋</span>\n          Subtasks\n        </h3>\n        <div class=\"subtasks-list\">\n          {CARD_SUBTASKS}\n          <div class=\"subtask-item{SUBTASK_COMPLETED_CLASS}\">\n            <span\n              style=\"display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; font-size: 14px; line-height: 1; flex-shrink: 0; margin-right: 4px; color: {SUBTASK_ICON_COLOR}; font-weight: bold;\"\n              >{SUBTASK_ICON}</span\n            >\n            <span>{SUBTASK_TEXT}</span>\n          </div>\n          {CARD_SUBTASKS}\n        </div>\n      </div>\n      {CARD_SUBTASKS_SECTION}\n\n      <div class=\"cta-section\">\n        <a href=\"{CARD_URL}\" class=\"cta-button\"> View Card in Ticky → </a>\n      </div>\n\n      <div class=\"footer\">\n        <div class=\"tip-box\">\n          <p>\n            <strong>💡 Tip:</strong> You can check who set this deadline in the\n            activity tab of the card.\n          </p>\n        </div>\n        <p>\n          This deadline reminder was sent by Ticky. Don't miss your deadline!\n        </p>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "Ticky.Web/wwwroot/emails/ForgottenPassword.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Password Reset - Ticky</title>\n    <style>\n      body {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n          Oxygen, Ubuntu, Cantarell, sans-serif;\n        line-height: 1.5;\n        color: #374151;\n        margin: 0;\n        padding: 20px;\n        background-color: #f1f5f9;\n      }\n      .container {\n        background-color: white;\n        border-radius: 12px;\n        padding: 32px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n          0 2px 4px -1px rgba(0, 0, 0, 0.06);\n        border: 1px solid #e2e8f0;\n        max-width: 420px;\n        margin: 0 auto;\n      }\n      .header {\n        text-align: center;\n        margin-bottom: 32px;\n        padding-bottom: 24px;\n        border-bottom: 1px solid #e2e8f0;\n      }\n      .title {\n        font-size: 22px;\n        font-weight: 600;\n        margin: 0;\n        color: #1f2937;\n      }\n      .reset-section {\n        background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n        border: 1px solid #f59e0b;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 24px 0;\n        text-align: center;\n      }\n      .reset-icon {\n        font-size: 24px;\n        margin-bottom: 8px;\n      }\n      .verification-code {\n        display: inline-block;\n        background-color: #dc2626;\n        color: white;\n        padding: 12px 20px;\n        border-radius: 8px;\n        font-family: \"SF Mono\", Monaco, \"Cascadia Code\", \"Roboto Mono\", Consolas,\n          \"Courier New\", monospace;\n        font-weight: 700;\n        font-size: 24px;\n        letter-spacing: 2px;\n        margin: 12px 0;\n        border: 2px solid #b91c1c;\n      }\n      .reset-text {\n        font-weight: 600;\n        color: #92400e;\n        margin: 8px 0 0 0;\n      }\n      .content-section {\n        background-color: #f8fafc;\n        border: 1px solid #e2e8f0;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 20px 0;\n      }\n      .section-title {\n        font-size: 16px;\n        font-weight: 600;\n        color: #374151;\n        margin: 0 0 12px 0;\n        display: flex;\n        align-items: center;\n      }\n      .section-title span {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 16px;\n        line-height: 1;\n        margin-right: 4px;\n      }\n      .description-text {\n        color: #6b7280;\n        margin: 0;\n        line-height: 1.6;\n      }\n      .footer {\n        margin-top: 32px;\n        padding-top: 24px;\n        border-top: 1px solid #e2e8f0;\n        font-size: 14px;\n        color: #6b7280;\n        text-align: center;\n      }\n      .footer p {\n        margin: 8px 0;\n      }\n      .warning-box {\n        background-color: #fee2e2;\n        border: 1px solid #fca5a5;\n        border-radius: 6px;\n        padding: 12px;\n        margin: 16px 0;\n      }\n      .warning-box p {\n        margin: 0;\n        color: #dc2626;\n        font-weight: 500;\n      }\n      .security-box {\n        background-color: #eff6ff;\n        border: 1px solid #bfdbfe;\n        border-radius: 6px;\n        padding: 12px;\n        margin: 16px 0;\n      }\n\n      @media screen and (max-width: 400px) {\n        body {\n          padding: 16px;\n        }\n        .container {\n          padding: 24px;\n        }\n        .verification-code {\n          font-size: 20px;\n          padding: 10px 16px;\n        }\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"header\">\n        <img\n          src=\"https://raw.githubusercontent.com/dkorecko/Ticky/refs/heads/main/Ticky.Web/wwwroot/images/ticky.png\"\n          alt=\"Ticky\"\n          style=\"\n            height: 40px;\n            margin-bottom: 8px;\n            display: block;\n            margin-left: auto;\n            margin-right: auto;\n          \"\n        />\n        <h1 class=\"title\">Password Reset</h1>\n      </div>\n\n      <div class=\"reset-section\">\n        <div class=\"reset-icon\">🔐</div>\n        <p class=\"reset-text\">Your password reset code is:</p>\n        <div class=\"verification-code\">{VERIFICATION_CODE}</div>\n      </div>\n\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📝</span>\n          Instructions\n        </h3>\n        <p class=\"description-text\">\n          Enter this code in the password reset form to create a new password\n          for your account.\n        </p>\n      </div>\n\n      <div class=\"footer\">\n        <div class=\"warning-box\">\n          <p>\n            <strong>⚠️ Important:</strong> This code will expire and can only be\n            used once.\n          </p>\n        </div>\n        <div class=\"security-box\">\n          <p>\n            <strong>🔒 Security Notice:</strong> If you didn't request a\n            password reset, please ignore this email and consider changing your\n            password.\n          </p>\n        </div>\n        <p>\n          This password reset email was sent by Ticky for your account security.\n        </p>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "Ticky.Web/wwwroot/emails/Reminder.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Reminder: {CARD_CODE}</title>\n    <style>\n      body {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n          Oxygen, Ubuntu, Cantarell, sans-serif;\n        line-height: 1.5;\n        color: #374151;\n        margin: 0;\n        padding: 20px;\n        background-color: #f1f5f9;\n      }\n      .container {\n        background-color: white;\n        border-radius: 12px;\n        padding: 32px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n          0 2px 4px -1px rgba(0, 0, 0, 0.06);\n        border: 1px solid #e2e8f0;\n        max-width: 420px;\n        margin: 0 auto;\n      }\n      .header {\n        text-align: center;\n        margin-bottom: 32px;\n        padding-bottom: 24px;\n        border-bottom: 1px solid #e2e8f0;\n      }\n      .card-code {\n        display: inline-block;\n        background-color: #dbeafe;\n        color: #1e40af;\n        padding: 6px 12px;\n        border-radius: 6px;\n        font-family: \"SF Mono\", Monaco, \"Cascadia Code\", \"Roboto Mono\", Consolas,\n          \"Courier New\", monospace;\n        font-weight: 600;\n        font-size: 14px;\n        margin-bottom: 12px;\n      }\n      .card-title {\n        font-size: 22px;\n        font-weight: 600;\n        margin: 0;\n        color: #1f2937;\n      }\n      .reminder-section {\n        background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);\n        border: 1px solid #f59e0b;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 24px 0;\n        text-align: center;\n      }\n      .reminder-icon {\n        font-size: 24px;\n        margin-bottom: 8px;\n      }\n      .reminder-text {\n        font-weight: 600;\n        color: #92400e;\n        margin: 0;\n      }\n      .content-section {\n        background-color: #f8fafc;\n        border: 1px solid #e2e8f0;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 20px 0;\n      }\n      .section-title {\n        font-size: 16px;\n        font-weight: 600;\n        color: #374151;\n        margin: 0 0 12px 0;\n        display: flex;\n        align-items: center;\n      }\n      .section-title span {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 16px;\n        line-height: 1;\n        margin-right: 4px;\n      }\n      .description-text {\n        color: #6b7280;\n        margin: 0;\n        line-height: 1.6;\n      }\n      .subtasks-list {\n        margin: 0;\n        padding-left: 0;\n        list-style: none;\n      }\n      .subtasks-list .subtask-item {\n        margin-bottom: 4px;\n      }\n      .subtasks-list .subtask-item:last-child {\n        margin-bottom: 0;\n      }\n      .subtask-item {\n        display: flex;\n        align-items: center;\n        padding: 10px 0;\n        border-bottom: 1px solid #e5e7eb;\n      }\n      .subtask-item span:first-child {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 14px;\n        line-height: 1;\n        flex-shrink: 0;\n        margin-right: 4px;\n      }\n      .subtask-item:last-child {\n        border-bottom: none;\n      }\n      .subtask-completed {\n        text-decoration: line-through;\n        color: #9ca3af;\n      }\n      .cta-section {\n        text-align: center;\n        margin: 32px 0;\n      }\n      .cta-button {\n        display: inline-block;\n        background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n        color: #ffffff !important;\n        padding: 14px 28px;\n        text-decoration: none;\n        border-radius: 8px;\n        font-weight: 600;\n        font-size: 16px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n        transition: all 0.2s;\n        border: 2px solid #1e40af;\n      }\n      .cta-button:hover {\n        background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);\n        transform: translateY(-1px);\n        box-shadow: 0 6px 8px -1px rgba(0, 0, 0, 0.15);\n        color: #ffffff !important;\n      }\n      .footer {\n        margin-top: 32px;\n        padding-top: 24px;\n        border-top: 1px solid #e2e8f0;\n        font-size: 14px;\n        color: #6b7280;\n        text-align: center;\n      }\n      .footer p {\n        margin: 8px 0;\n      }\n      .tip-box {\n        background-color: #eff6ff;\n        border: 1px solid #bfdbfe;\n        border-radius: 6px;\n        padding: 12px;\n        margin: 16px 0;\n      }\n\n      @media screen and (max-width: 400px) {\n        body {\n          padding: 16px;\n        }\n        .container {\n          padding: 24px;\n        }\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"header\">\n        <img\n          src=\"https://raw.githubusercontent.com/dkorecko/Ticky/refs/heads/main/Ticky.Web/wwwroot/images/ticky.png\"\n          alt=\"Ticky\"\n          style=\"\n            height: 40px;\n            margin-bottom: 8px;\n            display: block;\n            margin-left: auto;\n            margin-right: auto;\n          \"\n        />\n        <div class=\"card-code\">{CARD_CODE}</div>\n        <h1 class=\"card-title\">{CARD_TEXT}</h1>\n      </div>\n\n      <div class=\"reminder-section\">\n        <div class=\"reminder-icon\">⏰</div>\n        <p class=\"reminder-text\">Reminder scheduled for {CARD_SCHEDULED_FOR}</p>\n      </div>\n\n      {CARD_DESCRIPTION_SECTION}\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📝</span>\n          Description\n        </h3>\n        <p class=\"description-text\">{CARD_DESCRIPTION}</p>\n      </div>\n      {CARD_DESCRIPTION_SECTION} {CARD_DEADLINE_SECTION}\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📅</span>\n          Deadline\n        </h3>\n        <p class=\"description-text\">{CARD_DEADLINE}</p>\n      </div>\n      {CARD_DEADLINE_SECTION} {CARD_SUBTASKS_SECTION}\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>📋</span>\n          Subtasks\n        </h3>\n        <div class=\"subtasks-list\">\n          {CARD_SUBTASKS}\n          <div class=\"subtask-item{SUBTASK_COMPLETED_CLASS}\">\n            <span\n              style=\"display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; font-size: 14px; line-height: 1; flex-shrink: 0; margin-right: 4px; color: {SUBTASK_ICON_COLOR}; font-weight: bold;\"\n              >{SUBTASK_ICON}</span\n            >\n            <span>{SUBTASK_TEXT}</span>\n          </div>\n          {CARD_SUBTASKS}\n        </div>\n      </div>\n      {CARD_SUBTASKS_SECTION}\n\n      <div class=\"cta-section\">\n        <a href=\"{CARD_URL}\" class=\"cta-button\"> View Card in Ticky → </a>\n      </div>\n\n      <div class=\"footer\">\n        <div class=\"tip-box\">\n          <p>\n            <strong>💡 Tip:</strong> You can check who set this reminder in the\n            activity tab of the card.\n          </p>\n        </div>\n        <p>\n          This reminder was sent by Ticky. Manage your reminder preferences in\n          the card details.\n        </p>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "Ticky.Web/wwwroot/emails/VerifyEmail.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Verify Your Email - Ticky</title>\n    <style>\n      body {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\n          Oxygen, Ubuntu, Cantarell, sans-serif;\n        line-height: 1.5;\n        color: #374151;\n        margin: 0;\n        padding: 20px;\n        background-color: #f1f5f9;\n      }\n      .container {\n        background-color: white;\n        border-radius: 12px;\n        padding: 32px;\n        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n          0 2px 4px -1px rgba(0, 0, 0, 0.06);\n        border: 1px solid #e2e8f0;\n        max-width: 420px;\n        margin: 0 auto;\n      }\n      .header {\n        text-align: center;\n        margin-bottom: 32px;\n        padding-bottom: 24px;\n        border-bottom: 1px solid #e2e8f0;\n      }\n      .title {\n        font-size: 22px;\n        font-weight: 600;\n        margin: 0;\n        color: #1f2937;\n      }\n      .verification-section {\n        background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);\n        border: 1px solid #3b82f6;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 24px 0;\n        text-align: center;\n      }\n      .verification-icon {\n        font-size: 24px;\n        margin-bottom: 8px;\n      }\n      .verification-code {\n        display: inline-block;\n        background-color: #1e40af;\n        color: white;\n        padding: 12px 20px;\n        border-radius: 8px;\n        font-family: \"SF Mono\", Monaco, \"Cascadia Code\", \"Roboto Mono\", Consolas,\n          \"Courier New\", monospace;\n        font-weight: 700;\n        font-size: 24px;\n        letter-spacing: 2px;\n        margin: 12px 0;\n        border: 2px solid #1d4ed8;\n      }\n      .verification-text {\n        font-weight: 600;\n        color: #1e40af;\n        margin: 8px 0 0 0;\n      }\n      .content-section {\n        background-color: #f8fafc;\n        border: 1px solid #e2e8f0;\n        border-radius: 8px;\n        padding: 20px;\n        margin: 20px 0;\n      }\n      .section-title {\n        font-size: 16px;\n        font-weight: 600;\n        color: #374151;\n        margin: 0 0 12px 0;\n        display: flex;\n        align-items: center;\n      }\n      .section-title span {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 20px;\n        height: 20px;\n        font-size: 16px;\n        line-height: 1;\n        margin-right: 4px;\n      }\n      .description-text {\n        color: #6b7280;\n        margin: 0;\n        line-height: 1.6;\n      }\n      .footer {\n        margin-top: 32px;\n        padding-top: 24px;\n        border-top: 1px solid #e2e8f0;\n        font-size: 14px;\n        color: #6b7280;\n        text-align: center;\n      }\n      .footer p {\n        margin: 8px 0;\n      }\n      .warning-box {\n        background-color: #fef3c7;\n        border: 1px solid #f59e0b;\n        border-radius: 6px;\n        padding: 12px;\n        margin: 16px 0;\n      }\n      .warning-box p {\n        margin: 0;\n        color: #92400e;\n        font-weight: 500;\n      }\n\n      @media screen and (max-width: 400px) {\n        body {\n          padding: 16px;\n        }\n        .container {\n          padding: 24px;\n        }\n        .verification-code {\n          font-size: 20px;\n          padding: 10px 16px;\n        }\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"header\">\n        <img\n          src=\"https://raw.githubusercontent.com/dkorecko/Ticky/refs/heads/main/Ticky.Web/wwwroot/images/ticky.png\"\n          alt=\"Ticky\"\n          style=\"\n            height: 40px;\n            margin-bottom: 8px;\n            display: block;\n            margin-left: auto;\n            margin-right: auto;\n          \"\n        />\n        <h1 class=\"title\">Verify Your Email</h1>\n      </div>\n\n      <div class=\"verification-section\">\n        <div class=\"verification-icon\">✉️</div>\n        <p class=\"verification-text\">Your verification code is:</p>\n        <div class=\"verification-code\">{VERIFICATION_CODE}</div>\n      </div>\n\n      <div class=\"content-section\">\n        <h3 class=\"section-title\">\n          <span>ℹ️</span>\n          Instructions\n        </h3>\n        <p class=\"description-text\">\n          Enter this code in the verification form to complete your email\n          verification process.\n        </p>\n      </div>\n\n      <div class=\"footer\">\n        <div class=\"warning-box\">\n          <p>\n            <strong>⚠️ Important:</strong> This code will expire and can only be\n            used once.\n          </p>\n        </div>\n        <p>\n          This verification email was sent by Ticky. If you didn't request this,\n          please ignore this email.\n        </p>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "Ticky.Web/wwwroot/fonts/Noto-Sans.css",
    "content": "﻿/* cyrillic-ext */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5aPdu2ui.woff2) format('woff2');\n    unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5ardu2ui.woff2) format('woff2');\n    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* devanagari */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5a_du2ui.woff2) format('woff2');\n    unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09;\n}\n/* greek-ext */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5aLdu2ui.woff2) format('woff2');\n    unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5a3du2ui.woff2) format('woff2');\n    unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5aHdu2ui.woff2) format('woff2');\n    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5aDdu2ui.woff2) format('woff2');\n    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n    font-family: 'Noto Sans';\n    font-style: normal;\n    font-weight: 100 900;\n    font-stretch: 100%;\n    font-display: swap;\n    src: url(o-0bIpQlx3QUlC5A4PNB6Ryti20_6n1iPHjc5a7duw.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n"
  },
  {
    "path": "Ticky.Web/wwwroot/fonts/Poppins.css",
    "content": "﻿/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 100;\n    font-display: swap;\n    src: url(pxiGyp8kv8JHgFVrLPTucHtA.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 200;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLFj_Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 300;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLDz8Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 400;\n    font-display: swap;\n    src: url(pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 500;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 600;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 700;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 800;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLDD4Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin */\n@font-face {\n    font-family: 'Poppins';\n    font-style: normal;\n    font-weight: 900;\n    font-display: swap;\n    src: url(pxiByp8kv8JHgFVrLBT5Z1xlFQ.woff2) format('woff2');\n    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n"
  },
  {
    "path": "Ticky.Web/wwwroot/information.json",
    "content": "[\n  {\n    \"Id\": 1,\n    \"Title\": \"Planned Redesign\",\n    \"Message\": \"<b>Hello everyone &#x1f44b;</b><br/><br/>We are committed to make using Ticky as nice of an experience as possible and since it started as a school project initially, the design hasn't really received much love thus far. For some time now we have been working behind the scenes on giving it a fresh coat of paint. <a class='text-blue-600 hover:text-blue-800 underline hover:no-underline font-medium' href='https://www.figma.com/design/xWBSlplNjy2v1J9RoEQ82o/Ticky'>Here's the proposed new design.</a> If you would like to give your thoughts on the proposed changes (whether positive or negative), please visit this <a class='text-blue-600 hover:text-blue-800 underline hover:no-underline font-medium' href='https://github.com/dkorecko/Ticky/discussions/155'>GitHub discussion</a>, join our <a class='text-blue-600 hover:text-blue-800 underline hover:no-underline font-medium' href='https://discord.gg/DHCZqYwUUb'>Discord server</a> or submit an anonymous answer to <a class='text-blue-600 hover:text-blue-800 underline hover:no-underline font-medium' href='https://forms.gle/WZNdiynW8PY7Uh8x8'>this form</a>. If you are happy with this upcoming replacement, feel free to ignore this.<br/><br/>Thanks!\"\n  }\n]"
  },
  {
    "path": "Ticky.Web/wwwroot/js/darkTheme.js",
    "content": "﻿let currentItem = localStorage.getItem('Ticky_Theme')\nlet targetTheme = ''\n\nif (currentItem !== null) {\n    targetTheme = currentItem\n} else {\n    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n        targetTheme = 'dark'\n    }\n}\n\ndocument.querySelector('html').dataset.theme = targetTheme\n\nfunction switchTheme() {\n    document.querySelector('html').dataset.theme = document.querySelector('html').dataset.theme === 'dark' ? '' : 'dark';\n\n    localStorage.setItem('Ticky_Theme', document.querySelector('html').dataset.theme);\n}"
  },
  {
    "path": "Ticky.Web/wwwroot/js/downloadFile.js",
    "content": "function triggerFileDownload(fileName, url) {\n    const anchorElement = document.createElement('a');\n    anchorElement.href = url;\n    anchorElement.download = fileName ?? 'file';\n    anchorElement.click();\n    anchorElement.remove();\n}\n\nfunction downloadJsonText(fileName, jsonText) {\n    var anchorElement = document.createElement('a')\n    anchorElement.href = \"data:text/plain;charset=utf-8,\" + encodeURIComponent(jsonText.toString())\n    anchorElement.download = fileName ?? 'file'\n    anchorElement.click()\n    anchorElement.remove()\n}"
  },
  {
    "path": "Ticky.Web/wwwroot/js/focusTrap.js",
    "content": "// Focus trap for element\nfunction trapFocusInElement(element) {\n    if (!element) return;\n\n    const focusableSelectors = [\n        'a[href]', 'area[href]', 'input:not([disabled]):not([type=\"hidden\"])', 'select:not([disabled])',\n        'textarea:not([disabled])', 'button:not([disabled])', 'iframe', 'object', 'embed',\n        '[tabindex]:not([tabindex=\"-1\"])', '[contenteditable]'\n    ];\n\n    const visibleElements = Array.from(element.querySelectorAll(focusableSelectors.join(','))).filter(el => {\n        return el.offsetWidth > 0 || el.offsetHeight > 0 || el === document.activeElement;\n    });\n\n    if (!visibleElements.length) return;\n\n    const first = visibleElements[0];\n    const last = visibleElements[visibleElements.length - 1];\n\n    // Focus the first element only if not already focused\n    setTimeout(() => {\n        if (document.activeElement !== first) {\n            first.focus();\n        }\n    }, 0);\n\n    function handleTrap(e) {\n        if (e.key === 'Tab') {\n            if (e.shiftKey) {\n                if (document.activeElement === first) {\n                    e.preventDefault();\n                    last.focus();\n                }\n            } else {\n                if (document.activeElement === last) {\n                    e.preventDefault();\n                    first.focus();\n                }\n            }\n        }\n        if (e.key === 'Escape') {\n\t\t\tcloseDropdowns();\n        }\n    }\n    element.addEventListener('keydown', handleTrap);\n    function cleanup() {\n        element.removeEventListener('keydown', handleTrap);\n        element.removeEventListener('closeDropdowns', cleanup);\n    }\n\n    element.addEventListener('closeDropdowns', cleanup);\n}\n\nwindow.trapFocusInElement = trapFocusInElement;"
  },
  {
    "path": "Ticky.Web/wwwroot/js/main.js",
    "content": "const OPEN_OFFSET = 5;\n\nfunction positionDropdown(dropdownElement, left, top, width = null) {\n    //console.log('positioning')\n    dropdownElement.classList.remove('hidden');\n    dropdownElement.style.visibility = 'hidden';\n    if (width !== null) {\n        //console.log('width')\n        dropdownElement.style.width = width + 'px';\n    }\n    dropdownElement.style.left = left + 'px';\n    dropdownElement.style.top = top + 'px';\n\n    requestAnimationFrame(() => {\n        requestAnimationFrame(() => {\n            const rect = dropdownElement.getBoundingClientRect();\n            const mostRightPoint = left + rect.width;\n            const mostBottomPoint = top + rect.height;\n\n            const availableWidth = document.documentElement.clientWidth - (OPEN_OFFSET * 2)\n            const availableHeight = document.documentElement.clientHeight - (OPEN_OFFSET * 2)\n\n            if (mostRightPoint > availableWidth) {\n                if(availableWidth > rect.width) {\n                    dropdownElement.style.left = availableWidth - rect.width + 'px';\n                } else {\n                    dropdownElement.style.left = OPEN_OFFSET + 'px';\n                    dropdownElement.style.maxWidth = availableWidth + 'px';\n                }\n            }\n            if (mostBottomPoint > availableHeight) {\n                if(availableHeight > rect.height) {\n                    dropdownElement.style.top = availableHeight - rect.height + 'px';\n                } else {\n                    dropdownElement.style.top = OPEN_OFFSET + 'px';\n                    dropdownElement.style.maxHeight = availableHeight + 'px';\n                }\n            }\n\n            dropdownElement.style.visibility = 'visible';\n            void dropdownElement.offsetWidth;\n            dropdownElement.classList.add('dropdown-animate-in');\n            //console.log('positioning done')\n        });\n    });\n}\n\nlet openDropdown = null\nlet lastClosedX = null\nlet lastClosedY = null\nlet lastClickTarget = null\nlet lastOpenedFromTrigger = null\nlet isPreviousDropdownClosingAnimComplete = true\n\nfunction triggerConfetti(x, y) {\n    if (typeof confetti === 'undefined') {\n        console.warn('Confetti library not loaded. Skipping confetti trigger.')\n        return\n    }\n    confetti({\n        particleCount: 200,\n        angle: 20 + (Math.random()*170),\n        spread: 70,\n        origin: { y: y, x: x },\n        disableForReducedMotion: true\n    });\n}\n\ndocument.addEventListener('mouseup', (event) => {\n    if (openDropdown) {\n        if (openDropdown.contains(event.target))\n            return\n\n        //console.log('event mouseUp elsewhere')\n        lastClosedX = event.clientX\n        lastClosedY = event.clientY\n\n        if (lastOpenedFromTrigger === event.target) {\n            lastClickTarget = event.target\n            //console.log('settign lastClickTarget')\n        }\n\n        closeDropdowns()\n\n        setTimeout(resetLastClosed, 500)\n    }\n})\n\nfunction resetLastClosed() {\n    lastClosedX = null\n    lastClosedY = null\n    lastClickTarget = null\n    //console.log('reset lastClosed')\n}\n\nfunction closeDropdowns() {\n    if (!openDropdown)\n        return\n\n    //console.log('closing dropdown')\n\n    let targetDropdown = openDropdown\n    isPreviousDropdownClosingAnimComplete = false\n    targetDropdown.classList.remove('dropdown-animate-in')\n\n    setTimeout(() => {\n        targetDropdown.classList.add('hidden');\n        isPreviousDropdownClosingAnimComplete = true\n        //console.log('hidden')\n    }, 100);\n\n    openDropdown = null\n    lastOpenedFromTrigger = null\n}\n\nfunction openDropDownOnElementId(dropdownElement, triggerElementId) {\n    return openDropDownOnElementPosition(dropdownElement, document.getElementById(triggerElementId));\n}\n\nfunction openDropDownOnElementPosition(dropdownElement, triggerElement) {\n    if (!dropdownElement || !triggerElement)\n        return;\n\n    //console.log('dropdownElement')\n    //console.log(dropdownElement)\n\n    //console.log('triggerElement')\n    //console.log(triggerElement)\n\n    if (triggerElement === lastClickTarget) {\n        closeDropdowns();\n        resetLastClosed();\n        //console.log('matches lastClickTarget')\n        return;\n    }\n\n    lastOpenedFromTrigger = triggerElement;\n    //console.log('lastOpened ')\n    //console.log(lastOpenedFromTrigger)\n\n    setTimeout(() => {\n        const clientRect = triggerElement.getBoundingClientRect();\n        positionDropdown(dropdownElement, clientRect.left, clientRect.top + clientRect.height);\n        openDropdown = dropdownElement;\n        isPreviousDropdownClosingAnimComplete = true;\n    }, isPreviousDropdownClosingAnimComplete ? 0 : 100)\n}\n\nfunction onDropdownTriggerClicked(clientX, clientY, dropdownElement) {\n    if (!dropdownElement)\n        return\n\n    if (lastClosedX == clientX && lastClosedY == clientY) {\n        closeDropdowns()\n        resetLastClosed()\n        //console.log('dropdwonTriggerclicked reset')\n        return\n    }\n\n    positionDropdown(dropdownElement, clientX + OPEN_OFFSET, clientY + OPEN_OFFSET);\n    openDropdown = dropdownElement;\n}\n\nasync function copyText(text) {\n    \n    if (navigator.clipboard && window.isSecureContext) {\n        await navigator.clipboard.writeText(text);\n        return true;\n    }\n\n    \n    try {\n        const textArea = document.createElement(\"textarea\");\n        textArea.value = text;\n\n        textArea.style.position = \"absolute\";\n        textArea.style.left = \"-9999px\";\n        textArea.style.top = \"0\";\n\n        document.body.appendChild(textArea);\n\n        textArea.focus();\n        textArea.select();\n\n        const success = document.execCommand('copy');\n\n        document.body.removeChild(textArea);\n\n        if (!success) {\n            console.error('Copy command failed for both methods.');\n            return false;\n        }\n    } catch (err) {\n        console.error('Fallback copy operation failed:', err);\n        return false;\n    }\n}\n\n\nlet pasteHandler = null;\nlet pasteDotNetRef = null;\n\nfunction attachCardPasteHandler(dotNetReference, targetCardId) {\n    detachCardPasteHandler();\n    pasteDotNetRef = dotNetReference;\n\n    pasteHandler = function (e) {\n        const clipboardItems = e.clipboardData && e.clipboardData.items ? e.clipboardData.items : null;\n\n        if (!clipboardItems) \n            return;\n\n        for (let i = 0; i < clipboardItems.length; i++) {\n            const item = clipboardItems[i];\n\n            const file = typeof item.getAsFile === 'function' ? item.getAsFile() : null;\n            if (!file) continue;\n            const formData = new FormData();\n            formData.append('file', file, file.name);\n            formData.append('cardId', targetCardId);\n\n            fetch('/api/attachments/upload', {\n                method: 'POST',\n                body: formData,\n                credentials: 'same-origin'\n            }).then(response => {\n                if (!response.ok) {\n                    throw new Error(response.status);\n                }\n                if (pasteDotNetRef) pasteDotNetRef.invokeMethodAsync('OnPastedUploadFinished');\n            }).catch(() => {\n                if (pasteDotNetRef) pasteDotNetRef.invokeMethodAsync('OnPastedUploadFailed');\n            });\n        }\n    };\n\n    window.addEventListener('paste', pasteHandler);\n}\n\nfunction detachCardPasteHandler() {\n    if (pasteHandler) window.removeEventListener('paste', pasteHandler);\n    pasteHandler = null;\n    pasteDotNetRef = null;\n}\n\nfunction getElementScrollTop(element) {\n    try {\n        if (!element) return null;\n        return element.scrollTop;\n    } catch (e) {\n        return null;\n    }\n}\n\nfunction setElementScrollTop(element, value) {\n    try {\n        if (!element) return;\n        element.scrollTop = value;\n    } catch (e) {\n    }\n}"
  },
  {
    "path": "Ticky.Web/wwwroot/js/screenHeight.js",
    "content": "﻿function setViewportHeight() {\n    document.documentElement.style.setProperty('--vvh', `${window.visualViewport.height * 0.01}px`);\n}\n\n// Set the height on initial load and when the keyboard appears/disappears\nwindow.visualViewport.addEventListener('resize', setViewportHeight);\n\n// Call it once on page load to set the initial value\nsetViewportHeight();"
  },
  {
    "path": "Ticky.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.5.33209.295\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Ticky.Internal\", \"Ticky.Internal\\Ticky.Internal.csproj\", \"{6CF74B09-F595-41A6-B577-C195A3DC826D}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Ticky.Base\", \"Ticky.Base\\Ticky.Base.csproj\", \"{E3267CAC-DB33-4BF9-BE1C-1B46BB6E3526}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t.gitignore = .gitignore\n\t\t.github\\workflows\\build.yml = .github\\workflows\\build.yml\n\t\tCONTRIBUTING.md = CONTRIBUTING.md\n\t\t.github\\workflows\\docker-release.yml = .github\\workflows\\docker-release.yml\n\t\tDockerfile = Dockerfile\n\t\tREADME.md = README.md\n\tEndProjectSection\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Ticky.Web\", \"Ticky.Web\\Ticky.Web.csproj\", \"{B1E89F57-87FE-441E-AC21-DF0A38428C1E}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Ticky.Units\", \"Ticky.Units\\Ticky.Units.csproj\", \"{77FB83D5-5E37-4271-A561-0696212D9624}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{6CF74B09-F595-41A6-B577-C195A3DC826D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{6CF74B09-F595-41A6-B577-C195A3DC826D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{6CF74B09-F595-41A6-B577-C195A3DC826D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{6CF74B09-F595-41A6-B577-C195A3DC826D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{E3267CAC-DB33-4BF9-BE1C-1B46BB6E3526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E3267CAC-DB33-4BF9-BE1C-1B46BB6E3526}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E3267CAC-DB33-4BF9-BE1C-1B46BB6E3526}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E3267CAC-DB33-4BF9-BE1C-1B46BB6E3526}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{B1E89F57-87FE-441E-AC21-DF0A38428C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{B1E89F57-87FE-441E-AC21-DF0A38428C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{B1E89F57-87FE-441E-AC21-DF0A38428C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{B1E89F57-87FE-441E-AC21-DF0A38428C1E}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{77FB83D5-5E37-4271-A561-0696212D9624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{77FB83D5-5E37-4271-A561-0696212D9624}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{77FB83D5-5E37-4271-A561-0696212D9624}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{77FB83D5-5E37-4271-A561-0696212D9624}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {C4407ABF-5671-49C8-9310-0C8C4829530B}\n\tEndGlobalSection\nEndGlobal\n"
  }
]