Repository: dkorecko/Ticky
Branch: main
Commit: 971fd24c4179
Files: 241
Total size: 1.3 MB
Directory structure:
gitextract_dmiie922/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── build.yml
│ ├── docker-release.yml
│ └── docker-unstable.yml
├── .gitignore
├── .vscode/
│ └── settings.json
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.txt
├── README.md
├── Ticky.Base/
│ ├── Constants.cs
│ ├── Converters/
│ │ ├── ColorToInt32Converter.cs
│ │ └── StringToTimeSpanConverter.cs
│ ├── DTOs/
│ │ ├── InformationDTO.cs
│ │ ├── Notification.cs
│ │ ├── Trello/
│ │ │ ├── TrelloCardDTO.cs
│ │ │ ├── TrelloCheckItemDTO.cs
│ │ │ ├── TrelloChecklistDTO.cs
│ │ │ ├── TrelloLabelDTO.cs
│ │ │ ├── TrelloListDTO.cs
│ │ │ ├── TrelloMemberDTO.cs
│ │ │ └── TrelloPreferencesDTO.cs
│ │ └── TrelloImportDTO.cs
│ ├── Entities/
│ │ ├── Abstractions/
│ │ │ ├── AbstractDbEntity.cs
│ │ │ ├── IAssignable.cs
│ │ │ ├── IDbEntry.cs
│ │ │ ├── IDeletable.cs
│ │ │ └── IOrderable.cs
│ │ ├── Activity.cs
│ │ ├── Attachment.cs
│ │ ├── Board.cs
│ │ ├── BoardMembership.cs
│ │ ├── Card.cs
│ │ ├── CardLink.cs
│ │ ├── Code.cs
│ │ ├── Column.cs
│ │ ├── Comment.cs
│ │ ├── Favorite.cs
│ │ ├── Label.cs
│ │ ├── LastVisit.cs
│ │ ├── Owned/
│ │ │ └── RepeatInfo.cs
│ │ ├── Project.cs
│ │ ├── ProjectMembership.cs
│ │ ├── Reminder.cs
│ │ ├── Subtask.cs
│ │ ├── TimeRecord.cs
│ │ └── User.cs
│ ├── Enums/
│ │ ├── CardPlacement.cs
│ │ ├── CardPriority.cs
│ │ ├── CodePurpose.cs
│ │ ├── DeadlineColor.cs
│ │ ├── ImportSource.cs
│ │ ├── ImportType.cs
│ │ ├── NotificationType.cs
│ │ ├── OperationType.cs
│ │ ├── OrderRule.cs
│ │ ├── RepeatType.cs
│ │ └── TrelloArchivedHandlingType.cs
│ ├── GlobalUsings.cs
│ ├── Models/
│ │ ├── BoardPreferencesModel.cs
│ │ ├── CloneBoardModel.cs
│ │ ├── CreateCardModel.cs
│ │ ├── CredentialsModel.cs
│ │ ├── DeadlineModel.cs
│ │ ├── FilterCardsModel.cs
│ │ ├── ImportModel.cs
│ │ ├── LabelModel.cs
│ │ ├── LinkCardsModel.cs
│ │ ├── ReminderModel.cs
│ │ ├── RepeatCardModel.cs
│ │ ├── SnoozeCardModel.cs
│ │ ├── SubtaskModel.cs
│ │ ├── TimeRecordModel.cs
│ │ └── UserModel.cs
│ ├── Ticky.Base.csproj
│ └── Validation/
│ ├── IsValidTimeSpan.cs
│ └── RequiredIf.cs
├── Ticky.Internal/
│ ├── Data/
│ │ ├── DataContext.cs
│ │ ├── DataMigrator.cs
│ │ └── DataSeeder.cs
│ ├── GlobalUsings.cs
│ ├── Helpers/
│ │ ├── AttachmentHelper.cs
│ │ ├── IndexHelper.cs
│ │ ├── StringHelper.cs
│ │ └── TimeHelper.cs
│ ├── Migrations/
│ │ ├── 20250523175138_Initial.Designer.cs
│ │ ├── 20250523175138_Initial.cs
│ │ ├── 20250527093505_Favorites.Designer.cs
│ │ ├── 20250527093505_Favorites.cs
│ │ ├── 20250606115441_ForceCredentialsChange.Designer.cs
│ │ ├── 20250606115441_ForceCredentialsChange.cs
│ │ ├── 20250615181842_TextToNameCard.Designer.cs
│ │ ├── 20250615181842_TextToNameCard.cs
│ │ ├── 20250617140549_SnoozeCards.Designer.cs
│ │ ├── 20250617140549_SnoozeCards.cs
│ │ ├── 20250618090806_AtRemoval.Designer.cs
│ │ ├── 20250618090806_AtRemoval.cs
│ │ ├── 20250618114219_SelfAssign.Designer.cs
│ │ ├── 20250618114219_SelfAssign.cs
│ │ ├── 20250703124731_DisableBoardAnimations.Designer.cs
│ │ ├── 20250703124731_DisableBoardAnimations.cs
│ │ ├── 20250709130027_RepeatingCards.Designer.cs
│ │ ├── 20250709130027_RepeatingCards.cs
│ │ ├── 20250826115734_NewCardPlacement.Designer.cs
│ │ ├── 20250826115734_NewCardPlacement.cs
│ │ ├── 20251005111419_BlockToFlagged.Designer.cs
│ │ ├── 20251005111419_BlockToFlagged.cs
│ │ ├── 20251005174743_SubtaskAssignee.Designer.cs
│ │ ├── 20251005174743_SubtaskAssignee.cs
│ │ ├── 20251011134337_Information.Designer.cs
│ │ ├── 20251011134337_Information.cs
│ │ └── DataContextModelSnapshot.cs
│ ├── Services/
│ │ ├── AvatarService.cs
│ │ ├── CardNumberingService.cs
│ │ ├── CodeService.cs
│ │ ├── EmailService.cs
│ │ ├── Hosted/
│ │ │ ├── AbstractHostedService.cs
│ │ │ ├── CleanupHostedService.cs
│ │ │ ├── ReminderHostedService.cs
│ │ │ ├── RepeatHostedService.cs
│ │ │ └── SnoozeHostedService.cs
│ │ ├── InformationService.cs
│ │ ├── SearchService.cs
│ │ └── TrelloImportService.cs
│ └── Ticky.Internal.csproj
├── Ticky.Units/
│ ├── CardTest.cs
│ ├── Constants.cs
│ ├── GlobalUsings.cs
│ └── Ticky.Units.csproj
├── Ticky.Web/
│ ├── Components/
│ │ ├── App.razor
│ │ ├── Dialogs/
│ │ │ ├── AbstractModal.razor
│ │ │ ├── AddLabelModal.razor
│ │ │ ├── AddOrEditRepeatModal.razor
│ │ │ ├── AddReminderModal.razor
│ │ │ ├── AddSubtaskModal.razor
│ │ │ ├── AddTimeRecordModal.razor
│ │ │ ├── AddUserModal.razor
│ │ │ ├── AssigneesModal.razor
│ │ │ ├── CloneBoardModal.razor
│ │ │ ├── CreateBoardModal.razor
│ │ │ ├── CreateColumnModal.razor
│ │ │ ├── CreateProjectModal.razor
│ │ │ ├── DeleteConfirmationDialog.razor
│ │ │ ├── EditBoardMembershipsModal.razor
│ │ │ ├── EditBoardModal.razor
│ │ │ ├── EditCardModal.razor
│ │ │ ├── EditColumnModal.razor
│ │ │ ├── EditDeadlineModal.razor
│ │ │ ├── EditLabelModal.razor
│ │ │ ├── EditProjectMembershipsModal.razor
│ │ │ ├── EditProjectModal.razor
│ │ │ ├── EditSubtaskModal.razor
│ │ │ ├── EditTimeRecordModal.razor
│ │ │ ├── EditUserModal.razor
│ │ │ ├── FilterCardsModal.razor
│ │ │ ├── ImportModal.razor
│ │ │ ├── InformationModal.razor
│ │ │ ├── LabelModal.razor
│ │ │ ├── LinkCardsModal.razor
│ │ │ ├── PriorityModal.razor
│ │ │ ├── SearchModal.razor
│ │ │ ├── SnoozeCardModal.razor
│ │ │ └── UserInfoModal.razor
│ │ ├── Elements/
│ │ │ ├── ActionModal.razor
│ │ │ ├── BoardCard.razor
│ │ │ ├── CardView.razor
│ │ │ ├── ColumnView.razor
│ │ │ ├── DisabledBadge.razor
│ │ │ ├── Dropdown.razor
│ │ │ ├── LabelView.razor
│ │ │ ├── Modal.razor
│ │ │ ├── Notifications.razor
│ │ │ ├── PriorityLabel.razor
│ │ │ ├── Sortable/
│ │ │ │ ├── SortableList.razor
│ │ │ │ ├── SortableList.razor.cs
│ │ │ │ ├── SortableList.razor.css
│ │ │ │ └── SortableList.razor.js
│ │ │ ├── Spinner.razor
│ │ │ ├── SubtaskView.razor
│ │ │ ├── TimeSelect.razor
│ │ │ └── Tooltip.razor
│ │ ├── Layout/
│ │ │ ├── MainLayout.razor
│ │ │ └── NavMenu.razor
│ │ ├── Pages/
│ │ │ ├── Abstractions/
│ │ │ │ └── NotifiableBase.razor
│ │ │ ├── AdminPanel.razor
│ │ │ ├── Auth/
│ │ │ │ ├── ChangePassword.cshtml
│ │ │ │ ├── ChangePassword.cshtml.cs
│ │ │ │ ├── ConfirmMail.cshtml
│ │ │ │ ├── ConfirmMail.cshtml.cs
│ │ │ │ ├── ForgotPassword.cshtml
│ │ │ │ ├── ForgotPassword.cshtml.cs
│ │ │ │ ├── Login.cshtml
│ │ │ │ ├── Login.cshtml.cs
│ │ │ │ ├── Logout.cshtml
│ │ │ │ ├── Logout.cshtml.cs
│ │ │ │ ├── MailConfirmed.cshtml
│ │ │ │ ├── MailConfirmed.cshtml.cs
│ │ │ │ ├── PasswordChanged.cshtml
│ │ │ │ ├── PasswordChanged.cshtml.cs
│ │ │ │ ├── Register.cshtml
│ │ │ │ ├── Register.cshtml.cs
│ │ │ │ ├── _AuthLayout.cshtml
│ │ │ │ ├── _ViewImports.cshtml
│ │ │ │ └── _ViewStart.cshtml
│ │ │ ├── BoardSettings.razor
│ │ │ ├── BoardView.razor
│ │ │ ├── Error.razor
│ │ │ ├── Home.razor
│ │ │ └── UserSettings.razor
│ │ ├── Routes.razor
│ │ └── _Imports.razor
│ ├── Controllers/
│ │ ├── AttachmentsController.cs
│ │ └── HealthController.cs
│ ├── GlobalUsings.cs
│ ├── Hubs/
│ │ └── UpdateHub.cs
│ ├── Program.cs
│ ├── Properties/
│ │ └── launchSettings.json
│ ├── Ticky.Web.csproj
│ ├── app.css
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── package.json
│ ├── tailwind.config.js
│ ├── tailwind.extension.json
│ └── wwwroot/
│ ├── css/
│ │ └── app.css
│ ├── emails/
│ │ ├── DeadlineReminder.html
│ │ ├── ForgottenPassword.html
│ │ ├── Reminder.html
│ │ └── VerifyEmail.html
│ ├── fonts/
│ │ ├── Noto-Sans.css
│ │ └── Poppins.css
│ ├── information.json
│ └── js/
│ ├── darkTheme.js
│ ├── downloadFile.js
│ ├── focusTrap.js
│ ├── main.js
│ └── screenHeight.js
└── Ticky.sln
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [dkorecko]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: dkorecko
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**docker-compose.yaml**
```yaml
Provide your docker-compose.yaml file here.
```
**Logs**
Provide logs here if applicable.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: "[Feature]"
labels: enhancement
assignees: ''
---
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
================================================
FILE: .github/workflows/build.yml
================================================
name: Build app
on:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore
- name: Test
run: dotnet test -c Release --no-build
================================================
FILE: .github/workflows/docker-release.yml
================================================
name: Build and Publish Docker image to GHCR
on:
release:
types: [published]
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Extract release version
id: vars
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- name: Set lowercase repository name
id: repo-name
run: echo "REPO_LOWER=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ env.REPO_LOWER }}:${{ env.RELEASE_VERSION }}
ghcr.io/${{ env.REPO_LOWER }}:latest
================================================
FILE: .github/workflows/docker-unstable.yml
================================================
name: Build and publish unstable Docker image
on:
push:
branches:
- main
workflow_dispatch:
inputs:
branch:
description: "Branch to deploy"
required: true
default: "main"
concurrency:
group: docker-unstable-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.ref }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64,linux/arm
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Set lowercase repository name
id: repo-name
run: echo "REPO_LOWER=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm
file: ./Dockerfile
push: true
tags: ghcr.io/${{ env.REPO_LOWER }}:unstable
test-multi-arch:
needs: build-and-push
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
strategy:
matrix:
arch: [amd64, arm64, arm]
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/${{ matrix.arch }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Set lowercase repository name
id: repo-name
run: echo "REPO_LOWER=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
- name: Pull Docker image for ${{ matrix.arch }}
run: |
docker pull --platform linux/${{ matrix.arch }} ghcr.io/${{ env.REPO_LOWER }}:unstable
- name: Run test container for ${{ matrix.arch }}
run: |
docker run -p 8080:8080 -d --name ticky-test --platform linux/${{ matrix.arch }} ghcr.io/${{ env.REPO_LOWER }}:unstable
sleep 50
docker logs ticky-test
docker stop ticky-test
docker rm ticky-test
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
**/uploaded/**/*
# Idea
.idea/
================================================
FILE: .vscode/settings.json
================================================
{
"kiroAgent.configureMCP": "Disabled"
}
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Ticky
Thank you for considering contributing to Ticky! This document outlines the process for contributing to the project.
## How Can I Contribute?
### Reporting Bugs
Before 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).
When you are creating a bug report, please include as many details as possible:
- Use a clear and descriptive title
- Describe the exact steps to reproduce the problem
- Describe the behavior you observed and what you expected to see
- Include screenshots if possible
- Include details about your environment (OS, browser, etc.)
### Suggesting Enhancements
Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include:
- A clear and descriptive title
- A detailed description of the proposed functionality
- Any possible implementation details or ideas
- Why this enhancement would be useful to most users
### Pull Requests
Please follow these steps for submitting a pull request:
1. Fork the repository
2. Create a new branch for your feature (`git checkout -b feature/name-of-feature`)
3. Make your changes
4. Verify the changes
5. Commit your changes (`git commit -m 'Add some feature'`)
6. Push to your branch (`git push origin feature/name-of-feature`)
7. Open a Pull Request
#### Pull Request Guidelines
- Update the README.md with details of changes if applicable
- Follow the code style of the project
- Reference any relevant issues in your PR description
## Development Setup
### Prerequisites
- .NET 9.0 SDK
- MySQL Server 8.0+
- IDE (Visual Studio, VS Code, etc.)
### Setup Steps
1. Clone your fork of the repository
2. Configure your database and e-mail connection in user secrets
```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore.Database": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Production": "Server=localhost;Database=ticky;Uid=ticky;Pwd={PASSWORD_HERE};",
"Development": "Server=localhost;Database=ticky;Uid=ticky;Pwd={PASSWORD_HERE};"
},
"Email": {
"Server": "{SMTP_HOST}",
"Port": 465,
"SenderName": "Ticky",
"SenderEmail": "{SMTP_EMAIL}",
"Account": "{SMTP_USERNAME}",
"Password": "{SMTP_PASSWORD}",
"Security": true
}
}
```
3. Start the application: `dotnet watch --project Ticky.Web/Ticky.Web.csproj`
## Coding Conventions
- Use the built-in code formatter
- Follow C# naming conventions
- Add comments for complex logic
- Write descriptive commit messages
## Documentation
Good documentation is essential. Please update relevant documentation when making changes:
- Update the README.md if relevant
- Consider adding to the wiki for significant features
## Questions?
If you have any questions about contributing, please open an issue with your question.
Thank you for contributing to Ticky!
================================================
FILE: Dockerfile
================================================
# Declare ARGs for build platform and target architecture for clarity
ARG BUILDPLATFORM
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8080
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG TARGETARCH
WORKDIR /src
# Copy project files first for layer caching
COPY ["Ticky.Web/Ticky.Web.csproj", "Ticky.Web/"]
COPY ["Ticky.Internal/Ticky.Internal.csproj", "Ticky.Internal/"]
COPY ["Ticky.Base/Ticky.Base.csproj", "Ticky.Base/"]
# Map Docker's TARGETARCH to the arch used in .NET RIDs and restore dependencies
RUN export DOTNET_ARCH=$(case ${TARGETARCH} in \
"amd64") echo "x64" ;; \
"arm64") echo "arm64" ;; \
"arm") echo "arm" ;; \
*) echo "Unsupported architecture: ${TARGETARCH}"; exit 1 ;; \
esac) && \
dotnet restore "Ticky.Web/Ticky.Web.csproj" -r "linux-${DOTNET_ARCH}"
# Copy the rest of the source code
COPY . .
# Build and publish the application for the target runtime
RUN export DOTNET_ARCH=$(case ${TARGETARCH} in \
"amd64") echo "x64" ;; \
"arm64") echo "arm64" ;; \
"arm") echo "arm" ;; \
esac) && \
dotnet publish "Ticky.Web/Ticky.Web.csproj" \
-c Release \
-o /app/publish \
-r "linux-${DOTNET_ARCH}" \
--no-restore \
--self-contained false
# Final image stage
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "Ticky.Web.dll"]
================================================
FILE: LICENSE.txt
================================================
MIT License
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Ticky
Ticky 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.
## ❓ The why
You 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.
## 🌟 Features
Ticky is packed with powerful features designed to make your task management seamless and enjoyable:
- **Projects**: Create and manage projects to group your boards.
- **Boards**: Create and manage your own Kanban boards. You can even make them favorites to stay atop the list.
- **Templates**: You can clone boards, therefore allowing you to use boards as templates.
- **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.
- **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.
- **Subtasks**: Break down tasks into smaller, manageable subtasks with completion tracking.
- **Deadline Management**: Set and track deadlines with color-coded indicators.
- **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.
- **Labels and Priorities**: Organize tasks with custom labels and priority levels. Label colors are fully customizable.
- **Attachments**: Upload and manage files associated with tasks.
- **Reminders**: Set email reminders for tasks.
- **Card Linking**: Link related cards together (Jira-like).
- **Activity Tracking**: Monitor all changes and activities on tasks.
- **Comments**: Leave comments on cards to discuss and provide other useful information.
- **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.
- **Admin Panel**: For creating, editing and deleting users as an admin. Mostly for when not using SMTP.
- **Email Notifications**: Receive notifications for deadlines, and reminders.
- **Progress**: Track your progress within a board by seeing how many tasks have already been completed.
- **App-wide Search**: Find cards from other boards based on their unique identificator (like TEST-1), jump directly to them.
- **Recent board**: Immediately go back to your most recent board.
- **Auto-generated avatars** (optional): To make things more colorful.
- **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.
- **Dark Mode**: A sleek dark mode for less strain on your eyes.
- **Snooze Cards**: Reduce clutter by snoozing cards that cannot be worked on just yet.
- **Repeat Cards**: Automatically repeat cards at specified intervals, perfect for recurring tasks.
- **Responsive Design**: Take your tasks with you, no matter whether you are at your computer or running errands with just your phone.
- **Completion Confetti**: Feel the satisfaction of completing each task with a bunch of confetti, there to celebrate your success.
- **Filtering**: Easily find and organize tasks based on various criteria.
- **Trello import**: You can import your Trello boards, including the ability to map all the assigned members from your Trello board to Ticky users.
- ... and more!
## 📋 Prerequisites
- **Docker** installed on your system
- Windows: Download and install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)
- macOS: Download and install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)
- Linux: Install Docker Engine and Docker Compose via your package manager
- **Basic text editor** (Notepad, VS Code, etc.) to create/edit the configuration file
- **SMTP Server** (optional) - for email notifications and password resets
- Gmail, Outlook, or any email provider that supports SMTP
- If you don't have SMTP, Ticky will work without email features
## 🚀 Getting Started
### Using Docker (Recommended)
**Step 1: Verify Docker Installation**
Open a terminal/command prompt and run:
```bash
docker --version
```
If these commands work, you're ready to proceed!
**Step 2: Create Project Directory**
Create a new folder for Ticky on your computer:
```bash
mkdir ticky-app
cd ticky-app
```
**Step 3: Create Configuration File**
Create 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):
```yaml
services:
ticky-app:
image: ghcr.io/dkorecko/ticky:latest # or pin to a specific version (like v1.0.0) for manual updates
container_name: ticky-app
ports:
- "4088:8080"
restart: unless-stopped
volumes:
- ./data/app/uploaded:/app/wwwroot/uploaded
environment:
- DB_HOST=ticky-db
- DB_NAME=ticky # Database name, can be customized
- DB_USERNAME=ticky # Database username, can be customized
- DB_PASSWORD=your-secure-password
#- FULLY_OFFLINE=true # Uncomment this if you want to disable the avatar service and run fully offline.
#- DISABLE_USER_SIGNUPS=true # Uncomment to disable user self-registration. When true, only admins can create new users via the Admin Panel.
- 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.
- 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.
- SMTP_HOST=your-smtp-host
- SMTP_PORT=your-smtp-port
- SMTP_DISPLAY_NAME=Ticky
- SMTP_EMAIL=your-email@example.com
- SMTP_USERNAME=your-smtp-username
- SMTP_PASSWORD=your-smtp-password
- SMTP_SECURITY=true
depends_on:
ticky-db:
condition: service_healthy
ticky-db:
image: mysql:8
container_name: ticky-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ticky # This should match DB_NAME in ticky-app container
MYSQL_USER: ticky # This should match DB_USERNAME in ticky-app container
MYSQL_ROOT_PASSWORD: your-secure-password
MYSQL_PASSWORD: your-secure-password # This should match DB_PASSWORD
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 2s
retries: 30
volumes:
- ./data/mysql:/var/lib/mysql
```
**Step 4: Configure Email (Optional)**
If you want email notifications and password reset functionality:
- Replace `your-smtp-host`, `your-smtp-port`, `your-email@example.com`, etc. with your actual email provider settings
- For Gmail: Use `smtp.gmail.com`, port `587`, and create an [App Password](https://support.google.com/accounts/answer/185833)
- If you don't want email features, change `SMTP_ENABLED=true` to `SMTP_ENABLED=false`
**Step 5: Start Ticky**
In your terminal/command prompt, navigate to your project folder and run:
```bash
docker compose up -d
```
This will:
- Download the necessary Docker images (this may take a few minutes the first time)
- Create and start the Ticky application and database
- Set up data storage folders automatically
**Step 6: Access Your Ticky Instance**
1. Open your web browser and go to: `http://localhost:4088`
2. Log in with the default admin account:
- **Email**: `admin@ticky.com`
- **Password**: `abc123`
3. You'll be prompted to change these credentials immediately for improved security
4. After changing your password, you'll be logged out - just log back in with your new credentials
**Step 7: Add Users (If SMTP Disabled)**
If you disabled SMTP, you'll need to create user accounts manually through the Admin Panel. If SMTP is enabled, users can register themselves.
### Troubleshooting
- **Port already in use**: Change `4088:8080` to `4089:8080` (or any other available port) in the docker-compose.yaml file
- **Permission errors**: Make sure Docker Desktop is running and you have proper permissions. In Linux, sudo can be used in front of the commands.
- **Can't access the app**: Wait a minute after starting - the database needs time to initialize on first run
### Manual Setup
1. Clone the repository:
```
git clone https://github.com/dkorecko/Ticky.git
cd Ticky
```
2. Set up your environment variables.
3. Run the application:
```
dotnet run --project Ticky.Web/Ticky.Web.csproj
```
## 📷 Preview






## 🤝 Community
If 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.
## 🛠️ Project Structure
- **Ticky.Base**: Core entities, models, and shared components.
- **Ticky.Internal**: Data access, services, and business logic.
- **Ticky.Web**: Blazor web application, UI components, and user interface.
## 🔧 Configuration
### Database Setup
The application automatically applies migrations on startup.
## 🧪 Development
### Building
```
dotnet build
```
### Running Tests
```
dotnet test
```
### Watch Mode
```
dotnet watch
```
## 🔄 CI/CD
The project includes GitHub Actions workflows for CI/CD:
- Automated builds and tests on pull requests
- Docker image publishing to GitHub Container Registry (GHCR) on releases
## 📝 Contributing
Contributions are welcome! See the [CONTRIBUTING.md](CONTRIBUTING.md) file for details.
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 👏 Acknowledgements
- [Blazor](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor) - Web framework used
- [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) - ORM used
- [TailwindCSS](https://tailwindcss.com/) - CSS framework
- [Font Awesome](https://fontawesome.com/) - Icons
- [Sortable.js](https://github.com/SortableJS/Sortable) - Drag-and-drop functionality
## 📞 Contact
Have questions or feedback? I'd love to hear from you! Please feel free to open an issue on this repository.
---
Made with ❤️
================================================
FILE: Ticky.Base/Constants.cs
================================================
namespace Ticky.Base
{
public static class Constants
{
public static bool SMTP_ENABLED = true;
public static bool FULLY_OFFLINE;
public static bool DISABLE_USER_SIGNUPS = false;
public static string BASE_URL = string.Empty;
#if DEBUG
public const string APP_NAME = "Ticky [DEV]";
#else
public const string APP_NAME = "Ticky";
#endif
public static class CascadingParameters
{
public const string CurrentAccount = "CurrentAccount";
public const string MainLayout = "MainLayout";
}
public static class Defaults
{
public const string ADMIN_EMAIL = "admin@ticky.com";
public const string ADMIN_PASSWORD = "abc123";
}
public static class Emails
{
public static readonly string BASE_PATH = Path.Combine(WWW_ROOT, "emails");
public static class Mappings
{
public const string VERIFICATION_CODE = "{VERIFICATION_CODE}";
public const string CARD_CODE = "{CARD_CODE}";
public const string CARD_TEXT = "{CARD_TEXT}";
public const string CARD_SCHEDULED_FOR = "{CARD_SCHEDULED_FOR}";
public const string CARD_DESCRIPTION = "{CARD_DESCRIPTION}";
public const string CARD_SUBTASKS = "{CARD_SUBTASKS}";
public const string CARD_URL = "{CARD_URL}";
public const string BASE_URL = "{BASE_URL}";
public const string CARD_DEADLINE = "{CARD_DEADLINE}";
public const string CARD_DEADLINE_SECTION = "{CARD_DEADLINE_SECTION}";
public const string CARD_DESCRIPTION_SECTION = "{CARD_DESCRIPTION_SECTION}";
public const string CARD_SUBTASKS_SECTION = "{CARD_SUBTASKS_SECTION}";
public const string SUBTASK_TEXT = "{SUBTASK_TEXT}";
public const string SUBTASK_ICON = "{SUBTASK_ICON}";
public const string SUBTASK_ICON_COLOR = "{SUBTASK_ICON_COLOR}";
public const string SUBTASK_COMPLETED_CLASS = "{SUBTASK_COMPLETED_CLASS}";
}
}
public static class Hubs
{
public const string UPDATE_HUB = "/updatehub";
}
public static class Limits
{
public const int MINIMUM_SECOND_HOSTED_SERVICE_DELAY = 15;
public const int DEFAULT_NOTIFICATION_TIME_IN_MS = 5000;
public const int FILE_NAME_LENGTH = 10;
public const long MAX_FILE_SIZE = 15360 * 1024;
public const long MAX_IMAGE_SIZE = MAX_FILE_SIZE;
public const long MAX_JSON_SIZE = MAX_FILE_SIZE;
public const int MAX_FILES = 20;
public const int DEBOUNCE_TIME_IN_MS = 1000;
}
public static class Mappings
{
public const string LOGIN_PATH = "/auth/login";
public const string LOGOUT_PATH = "/auth/logout";
public const string BOARD_PATH = "/boards";
public const string ATTACHMENTS_API_PATH = "/api/attachments";
public const string ATTACHMENTS_DOWNLOAD_PATH = ATTACHMENTS_API_PATH + "/download";
}
public static class Policies
{
public const string RequireAdmin = "RequireAdmin";
}
public static class Roles
{
public const string Admin = "Admin";
}
public static class StorageKeys
{
public const string BoardPreferences = "Ticky_BoardPreferences";
public const string FilterPreferencesPrefix = "Ticky_FilterPreferences";
}
public static readonly string WWW_ROOT = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"wwwroot"
);
public static readonly string INFORMATION_PATH = Path.Combine(WWW_ROOT, "information.json");
public static readonly string SAVE_UPLOADED_PATH = $"wwwroot/uploaded";
public static readonly string SAVE_UPLOADED_IMAGES_PATH = $"{SAVE_UPLOADED_PATH}/images";
public static readonly string SAVE_UPLOADED_FILES_PATH = $"{SAVE_UPLOADED_PATH}/files";
public static readonly string ACCESS_UPLOADED_PATH = $"./uploaded";
public static readonly string ACCESS_UPLOADED_IMAGES_PATH =
$"{ACCESS_UPLOADED_PATH}/images";
public static readonly string ACCESS_UPLOADED_FILES_PATH = $"{ACCESS_UPLOADED_PATH}/files";
public const string REPEATED_KEY = "is repeated by";
public static readonly Dictionary LINK_TYPE_PAIRS =
new()
{
{ "is blocked by", "blocks" },
{ "is tested by", "tests" },
{ "relates to", "relates to" },
{ REPEATED_KEY, "repeats" }
};
}
}
================================================
FILE: Ticky.Base/Converters/ColorToInt32Converter.cs
================================================
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Ticky.Base.Converters;
public class ColorToInt32Converter : ValueConverter
{
public ColorToInt32Converter()
: base(c => c.ToArgb(), v => Color.FromArgb(v)) { }
}
================================================
FILE: Ticky.Base/Converters/StringToTimeSpanConverter.cs
================================================
namespace Ticky.Base.Converters;
public static class StringToTimeSpanConverter
{
public static TimeSpan ConvertToTimeSpan(this string str)
{
var time = new TimeSpan();
foreach (var part in str.Split(' '))
{
if (part.EndsWith("h", StringComparison.OrdinalIgnoreCase))
time = time.Add(TimeSpan.FromHours(int.Parse(part.TrimEnd('h'))));
else if (part.EndsWith("m", StringComparison.OrdinalIgnoreCase))
time = time.Add(TimeSpan.FromMinutes(int.Parse(part.TrimEnd('m'))));
else if (part.EndsWith("s", StringComparison.OrdinalIgnoreCase))
time = time.Add(TimeSpan.FromSeconds(int.Parse(part.TrimEnd('s'))));
else
throw new InvalidDataException();
}
return time;
}
public static string ConvertToString(this TimeSpan time)
{
string result = string.Empty;
if (time.Hours > 0)
result += $"{time.Hours}h ";
if (time.Minutes > 0)
result += $"{time.Minutes}m ";
if (time.Seconds > 0 || string.IsNullOrWhiteSpace(result))
result += $"{time.Seconds}s ";
return result.Trim();
}
}
================================================
FILE: Ticky.Base/DTOs/InformationDTO.cs
================================================
namespace Ticky.Base.DTOs;
public class InformationDTO
{
public required string Title { get; set; }
public required string Message { get; set; }
public required int Id { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Notification.cs
================================================
namespace Ticky.Base.DTOs;
public record Notification(string text, NotificationType type = NotificationType.Success)
{
public NotificationType Type { get; set; } = type;
public string Text { get; set; } = text;
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloCardDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloCardDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("desc")]
public required string Description { get; set; }
[JsonPropertyName("closed")]
public required bool Closed { get; set; }
[JsonPropertyName("due")]
public required DateTime? Due { get; set; }
[JsonPropertyName("idList")]
public required string IdList { get; set; }
[JsonPropertyName("idLabels")]
public required List IdLabels { get; set; }
[JsonPropertyName("mirrorSourceId")]
public required string MirrorSourceId { get; set; }
[JsonPropertyName("dueComplete")]
public required bool DueComplete { get; set; }
[JsonPropertyName("dateCompleted")]
public required DateTime? DateCompleted { get; set; }
[JsonPropertyName("dueReminder")]
public required int? DueReminder { get; set; }
[JsonPropertyName("idMembers")]
public required List IdMembers { get; set; }
[JsonPropertyName("idMemberCreator")]
public required string IdMemberCreator { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloCheckItemDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloCheckItemDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("idChecklist")]
public required string IdChecklist { get; set; }
[JsonPropertyName("state")]
public required string State { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloChecklistDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloChecklistDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("idCard")]
public required string IdCard { get; set; }
[JsonPropertyName("checkItems")]
public required List CheckItems { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloLabelDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello
{
public class TrelloLabelDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("color")]
public required string Color { get; set; }
}
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloListDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloListDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("closed")]
public bool Closed { get; set; }
[JsonPropertyName("softLimit")]
public int? SoftLimit { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloMemberDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloMemberDTO
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("fullName")]
public required string FullName { get; set; }
[JsonPropertyName("username")]
public required string Username { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/Trello/TrelloPreferencesDTO.cs
================================================
namespace Ticky.Base.DTOs.Trello;
public class TrelloPreferencesDTO
{
[JsonPropertyName("selfJoin")]
public required bool SelfJoin { get; set; }
}
================================================
FILE: Ticky.Base/DTOs/TrelloImportDTO.cs
================================================
using Ticky.Base.DTOs.Trello;
namespace Ticky.Base.DTOs;
public class TrelloImportDTO
{
[JsonPropertyName("name")]
public required string Name { get; set; }
[JsonPropertyName("desc")]
public required string Description { get; set; }
[JsonPropertyName("starred")]
public required bool Starred { get; set; }
[JsonPropertyName("prefs")]
public required TrelloPreferencesDTO Preferences { get; set; }
[JsonPropertyName("lists")]
public required List Lists { get; set; }
[JsonPropertyName("cards")]
public required List Cards { get; set; }
[JsonPropertyName("checklists")]
public required List Checklists { get; set; }
[JsonPropertyName("labels")]
public required List Labels { get; set; }
[JsonPropertyName("members")]
public required List Members { get; set; }
}
================================================
FILE: Ticky.Base/Entities/Abstractions/AbstractDbEntity.cs
================================================
namespace Ticky.Base.Entities.Abstractions;
public abstract class AbstractDbEntity : IDbEntry
{
public int Id { get; set; }
public DateTime CreatedAt { get; init; } = DateTime.Now;
}
================================================
FILE: Ticky.Base/Entities/Abstractions/IAssignable.cs
================================================
namespace Ticky.Base.Entities.Abstractions;
public interface IAssignable
{
public List Assignees { get; }
}
================================================
FILE: Ticky.Base/Entities/Abstractions/IDbEntry.cs
================================================
namespace Ticky.Base.Entities.Abstractions;
public interface IDbEntry
{
public int Id { get; set; }
public DateTime CreatedAt { get; }
}
================================================
FILE: Ticky.Base/Entities/Abstractions/IDeletable.cs
================================================
namespace Ticky.Base.Entities.Abstractions;
public interface IDeletable : IDbEntry
{
public string Name { get; }
}
================================================
FILE: Ticky.Base/Entities/Abstractions/IOrderable.cs
================================================
namespace Ticky.Base.Entities.Abstractions;
public interface IOrderable
{
public int Index { get; set; }
}
================================================
FILE: Ticky.Base/Entities/Activity.cs
================================================
namespace Ticky.Base.Entities;
public class Activity : AbstractDbEntity
{
public required int UserId { get; set; }
public virtual User User { get; set; } = null!;
public required string Text { get; set; }
public required int CardId { get; set; }
public virtual Card Card { get; set; } = null!;
}
================================================
FILE: Ticky.Base/Entities/Attachment.cs
================================================
namespace Ticky.Base.Entities;
public class Attachment : AbstractDbEntity
{
public required string FileName { get; set; }
public required string OriginalName { get; set; }
public required int CardId { get; set; }
public virtual Card Card { get; set; } = null!;
}
================================================
FILE: Ticky.Base/Entities/Board.cs
================================================
namespace Ticky.Base.Entities;
public class Board : AbstractDbEntity, IDeletable
{
[Required(AllowEmptyStrings = false)]
public required string Name { get; set; }
public required string Description { get; set; }
[Required(AllowEmptyStrings = false)]
[MinLength(1)]
[MaxLength(5)]
[RegularExpression("^[A-Z]*$", ErrorMessage = "The code must be in upper-case.")]
public required string Code { get; set; }
public required int ProjectId { get; set; }
public virtual Project Project { get; set; } = null!;
public virtual List Columns { get; set; } = [];
public virtual List Memberships { get; set; } = [];
public virtual List