├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── doc_improvement.md │ └── enhancement.md ├── codeql │ └── codeql-config.yml └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── dev-release.yml │ ├── lint-server.yml │ ├── prod-release.yml │ └── scorecards-analysis.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitpod.yml ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile.build ├── LICENSE.txt ├── Makefile ├── NOTICE.txt ├── README.md ├── SECURITY.md ├── app-config.json ├── config.json ├── docker-testing ├── docker-compose-mariadb.yml ├── docker-compose-mysql.yml └── docker-compose-postgres.yml ├── docker ├── Dockerfile ├── README.md ├── config.json ├── docker-compose-db-nginx.yml ├── docker-compose.yml └── server_config.json ├── docs ├── README.md ├── _config.yml ├── board-metrics.md ├── code-review.md ├── contribution-checklist.md ├── contributions-without-ticket.md ├── core-committers.md ├── create-new-board.md ├── dev-tips.md ├── focalboard-dev-guide.md ├── focalboard-plugin-end-user-guide.md ├── get-started-with-board-templates.md ├── group-filter-sort-boards.md ├── import-export-backup-data.md ├── index.md ├── link-boards-to-mattermost-channels.md ├── manage-boards.md ├── manage-plugin-preferences.md ├── plugin-data-being-collected.md ├── share-collaborate.md ├── work-with-board-views.md └── work-with-cards.md ├── experiments └── webext │ ├── .gitignore │ ├── .parcelrc │ ├── README.md │ ├── icons │ ├── 19.png │ ├── 38.png │ ├── 48.png │ └── 96.png │ ├── manifest.json │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── utils │ │ ├── Board.ts │ │ ├── networking.ts │ │ └── settings.ts │ └── views │ │ ├── OptionsApp.scss │ │ ├── OptionsApp.tsx │ │ ├── PopupApp.scss │ │ ├── PopupApp.tsx │ │ ├── options.html │ │ ├── options.tsx │ │ ├── popup.html │ │ └── popup.tsx │ └── tsconfig.json ├── import ├── README.md ├── asana │ ├── .eslintrc.json │ ├── .gitignore │ ├── .vscode │ │ ├── launch.json │ │ └── settings.json │ ├── README.md │ ├── asana.ts │ ├── importAsana.ts │ ├── package-lock.json │ ├── package.json │ ├── tsconfig.json │ └── utils.ts ├── jira │ ├── .gitignore │ ├── README.md │ ├── importJira.ts │ ├── jiraImporter.test.ts │ ├── jiraImporter.ts │ ├── package-lock.json │ ├── package.json │ ├── test │ │ └── jira-export.xml │ ├── tsconfig.json │ └── utils.ts ├── nextcloud-deck │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── deck.ts │ ├── importDeck.ts │ ├── package-lock.json │ ├── package.json │ ├── tsconfig.json │ └── utils.ts ├── notion │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── importNotion.ts │ ├── package-lock.json │ ├── package.json │ ├── tsconfig.json │ └── utils.ts ├── todoist │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── importTodoist.ts │ ├── package-lock.json │ ├── package.json │ ├── todoist.ts │ ├── tsconfig.json │ └── utils.ts ├── trello │ ├── .eslintrc.json │ ├── .gitignore │ ├── .vscode │ │ ├── launch.json │ │ └── settings.json │ ├── README.md │ ├── importTrello.ts │ ├── package-lock.json │ ├── package.json │ ├── trello.ts │ ├── tsconfig.json │ └── utils.ts └── util │ └── archive.ts ├── linux ├── Makefile ├── config.json ├── go.mod ├── go.sum ├── main.go ├── pack └── webapp ├── mac ├── Focalboard.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Focalboard.xcscheme ├── Focalboard.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Focalboard │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── focalboard-1024.png │ │ │ └── focalboard-512.png │ │ └── Contents.json │ ├── AutoSaveWindowController.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── CustomWKWebView.swift │ ├── DownloadHandler.swift │ ├── Focalboard.entitlements │ ├── Globals.swift │ ├── Info.plist │ ├── Inherit.entitlements │ ├── PortUtils.swift │ ├── ViewController.swift │ ├── WhatsNewViewController.swift │ └── whatsnew.txt ├── FocalboardTests │ ├── FocalboardTests.swift │ └── Info.plist ├── FocalboardUITests │ ├── FocalboardUITests.swift │ └── Info.plist ├── README.md └── export.plist ├── modd-servertest.conf ├── modd.conf ├── noticegen ├── Readme.md └── config.yaml ├── pull_request_template.md ├── responsible_disclosure_policy.md ├── server-config.json ├── server ├── .golangci.yml ├── admin-scripts │ └── reset-password.sh ├── api │ ├── admin.go │ ├── api.go │ ├── api_test.go │ ├── archive.go │ ├── audit.go │ ├── auth.go │ ├── blocks.go │ ├── boards.go │ ├── boards_and_blocks.go │ ├── cards.go │ ├── categories.go │ ├── channels.go │ ├── compliance.go │ ├── config.go │ ├── content_blocks.go │ ├── context.go │ ├── files.go │ ├── members.go │ ├── onboarding.go │ ├── search.go │ ├── sharing.go │ ├── statistics.go │ ├── subscriptions.go │ ├── system.go │ ├── system_test.go │ ├── teams.go │ ├── templates.go │ └── users.go ├── app │ ├── app.go │ ├── app_test.go │ ├── auth.go │ ├── auth_test.go │ ├── blocks.go │ ├── blocks_test.go │ ├── boards.go │ ├── boards_and_blocks.go │ ├── boards_test.go │ ├── cards.go │ ├── cards_test.go │ ├── category.go │ ├── category_boards.go │ ├── category_boards_test.go │ ├── category_test.go │ ├── clientConfig.go │ ├── clientConfig_test.go │ ├── compliance.go │ ├── content_blocks.go │ ├── content_blocks_test.go │ ├── export.go │ ├── files.go │ ├── files_test.go │ ├── helper_test.go │ ├── import.go │ ├── import_test.go │ ├── initialize.go │ ├── onboarding.go │ ├── onboarding_test.go │ ├── permissions.go │ ├── server_metadata.go │ ├── server_metadata_test.go │ ├── sharing.go │ ├── sharing_test.go │ ├── statistics.go │ ├── subscriptions.go │ ├── teams.go │ ├── teams_test.go │ ├── templates.boardarchive │ ├── templates.go │ ├── templates_test.go │ ├── user.go │ └── user_test.go ├── assets │ ├── assets.go │ ├── build-template-archive │ │ └── main.go │ ├── templates-boardarchive │ │ ├── b7wnw9awd4pnefryhq51apbzb4c │ │ │ └── board.jsonl │ │ ├── bbkpwdj8x17bdpdqd176n8ctoua │ │ │ └── board.jsonl │ │ ├── bbn1888mprfrm5fjw9f1je9x3xo │ │ │ ├── 76fwrj36hptg6dywka4k5mt3sph.png │ │ │ └── board.jsonl │ │ ├── bc41mwxg9ybb69pn9j5zna6d36c │ │ │ └── board.jsonl │ │ ├── bcm39o11e4ib8tye8mt6iyuec9o │ │ │ └── board.jsonl │ │ ├── bd65qbzuqupfztpg31dgwgwm5ga │ │ │ └── board.jsonl │ │ ├── bgi1yqiis8t8xdqxgnet8ebutky │ │ │ ├── 7b9xk9boj3fbqfm3umeaaizp8qr.png │ │ │ ├── 7tmfu5iqju3n1mdfwi5gru89qmw.png │ │ │ └── board.jsonl │ │ ├── bh4pkixqsjift58e1qy6htrgeay │ │ │ └── board.jsonl │ │ ├── bkqk6hpfx7pbsucue7jan5n1o1o │ │ │ └── board.jsonl │ │ ├── brs9cdimfw7fodyi7erqt747rhc │ │ │ ├── 7y5kr8x8ybpnwdykjfuz57rggrh.png │ │ │ └── board.jsonl │ │ ├── bsjd59qtpbf888mqez3ge77domw │ │ │ └── board.jsonl │ │ ├── bui5izho7dtn77xg3thkiqprc9r │ │ │ ├── 77pe9r4ckbin438ph3f18bpatua.png │ │ │ ├── 7pbp4qg415pbstc6enzeicnu3qh.png │ │ │ └── board.jsonl │ │ ├── buixxjic3xjfkieees4iafdrznc │ │ │ ├── 74nt9eqzea3ydjjpgjtsxcjgrxc.gif │ │ │ ├── 74uia99m9btr8peydw7oexn37tw.gif │ │ │ ├── 78jws5m1myf8pufewzkaa6i11sc.gif │ │ │ ├── 7d6hrtig3zt8f9cnbo1um5oxx3y.gif │ │ │ ├── 7dybb6t8fj3nrdft7nerhuf784y.png │ │ │ ├── 7ek6wbpp19jfoujs1goh6kttbby.gif │ │ │ ├── 7iw4rxx7jj7bypmdotd9z469cyh.png │ │ │ ├── 7knxbyuiedtdafcgmropgkrtybr.gif │ │ │ └── board.jsonl │ │ └── version.json │ └── templates.boardarchive ├── auth │ ├── auth.go │ ├── auth_test.go │ └── mocks │ │ └── mockauth_interface.go ├── client │ └── client.go ├── go.mod ├── go.sum ├── go.tools.mod ├── go.tools.sum ├── integrationtests │ ├── blocks_test.go │ ├── board_test.go │ ├── boards_and_blocks_test.go │ ├── cards_test.go │ ├── clienttestlib.go │ ├── compliance_test.go │ ├── content_blocks_test.go │ ├── export_test.go │ ├── file_test.go │ ├── permissions_test.go │ ├── pluginteststore.go │ ├── sharing_test.go │ ├── sidebar_test.go │ ├── subscriptions_test.go │ ├── teststore.go │ ├── user_test.go │ └── work_template_test.go ├── main │ ├── doc.go │ └── main.go ├── model │ ├── auth.go │ ├── block.go │ ├── block_test.go │ ├── blockid.go │ ├── blocktype.go │ ├── board.go │ ├── board_statistics.go │ ├── boards_and_blocks.go │ ├── boards_and_blocks_test.go │ ├── card.go │ ├── card_test.go │ ├── category.go │ ├── category_boards.go │ ├── clientConfig.go │ ├── cloud.go │ ├── compliance.go │ ├── database.go │ ├── error.go │ ├── errorResponse.go │ ├── file.go │ ├── import_export.go │ ├── log_level.go │ ├── mocks │ │ ├── mockservicesapi.go │ │ └── propValueResolverMock.go │ ├── notification.go │ ├── permission.go │ ├── properties.go │ ├── properties_test.go │ ├── services_api.go │ ├── sharing.go │ ├── subscription.go │ ├── team.go │ ├── user.go │ ├── util.go │ └── version.go ├── server │ ├── initHandlers.go │ ├── params.go │ └── server.go ├── services │ ├── audit │ │ ├── audit.go │ │ ├── record.go │ │ └── record_test.go │ ├── auth │ │ ├── email.go │ │ ├── password.go │ │ ├── password_test.go │ │ ├── request_parser.go │ │ └── request_parser_test.go │ ├── config │ │ └── config.go │ ├── metrics │ │ ├── metrics.go │ │ └── service.go │ ├── notify │ │ ├── notifylogger │ │ │ └── logger_backend.go │ │ ├── notifymentions │ │ │ ├── app_api.go │ │ │ ├── delivery.go │ │ │ ├── extract.go │ │ │ ├── extract_test.go │ │ │ ├── mentions.go │ │ │ ├── mentions_backend.go │ │ │ └── mentions_test.go │ │ ├── notifysubscriptions │ │ │ ├── app_api.go │ │ │ ├── delivery.go │ │ │ ├── diff.go │ │ │ ├── diff2markdown.go │ │ │ ├── diff2markdown_test.go │ │ │ ├── diff2slackattachments.go │ │ │ ├── notifier.go │ │ │ ├── subscriptions_backend.go │ │ │ └── util.go │ │ ├── plugindelivery │ │ │ ├── mention_deliver.go │ │ │ ├── message.go │ │ │ ├── plugin_delivery.go │ │ │ ├── subscription_deliver.go │ │ │ ├── user.go │ │ │ └── user_test.go │ │ └── service.go │ ├── permissions │ │ ├── localpermissions │ │ │ ├── helpers_test.go │ │ │ ├── localpermissions.go │ │ │ └── localpermissions_test.go │ │ ├── mmpermissions │ │ │ ├── helpers_test.go │ │ │ ├── mmpermissions.go │ │ │ ├── mmpermissions_test.go │ │ │ └── mocks │ │ │ │ └── mockpluginapi.go │ │ ├── mocks │ │ │ └── mockstore.go │ │ └── permissions.go │ ├── scheduler │ │ ├── scheduler.go │ │ └── scheduler_test.go │ ├── store │ │ ├── generators │ │ │ ├── main.go │ │ │ └── transactional_store.go.tmpl │ │ ├── mattermostauthlayer │ │ │ ├── mattermostauthlayer.go │ │ │ └── mattermostauthlayer_test.go │ │ ├── mockstore │ │ │ └── mockstore.go │ │ ├── sqlstore │ │ │ ├── blocks.go │ │ │ ├── board.go │ │ │ ├── boards_and_blocks.go │ │ │ ├── category.go │ │ │ ├── category_boards.go │ │ │ ├── cloud.go │ │ │ ├── compliance.go │ │ │ ├── data_migrations.go │ │ │ ├── data_migrations_test.go │ │ │ ├── data_retention.go │ │ │ ├── file.go │ │ │ ├── helpers_test.go │ │ │ ├── legacy_blocks.go │ │ │ ├── migrate.go │ │ │ ├── migrations │ │ │ │ ├── 000001_init.down.sql │ │ │ │ ├── 000001_init.up.sql │ │ │ │ ├── 000002_system_settings_table.down.sql │ │ │ │ ├── 000002_system_settings_table.up.sql │ │ │ │ ├── 000003_blocks_rootid.down.sql │ │ │ │ ├── 000003_blocks_rootid.up.sql │ │ │ │ ├── 000004_auth_table.down.sql │ │ │ │ ├── 000004_auth_table.up.sql │ │ │ │ ├── 000005_blocks_modifiedby.down.sql │ │ │ │ ├── 000005_blocks_modifiedby.up.sql │ │ │ │ ├── 000006_sharing_table.down.sql │ │ │ │ ├── 000006_sharing_table.up.sql │ │ │ │ ├── 000007_workspaces_table.down.sql │ │ │ │ ├── 000007_workspaces_table.up.sql │ │ │ │ ├── 000008_teams.down.sql │ │ │ │ ├── 000008_teams.up.sql │ │ │ │ ├── 000009_blocks_history.down.sql │ │ │ │ ├── 000009_blocks_history.up.sql │ │ │ │ ├── 000010_blocks_created_by.down.sql │ │ │ │ ├── 000010_blocks_created_by.up.sql │ │ │ │ ├── 000011_match_collation.down.sql │ │ │ │ ├── 000011_match_collation.up.sql │ │ │ │ ├── 000012_match_column_collation.down.sql │ │ │ │ ├── 000012_match_column_collation.up.sql │ │ │ │ ├── 000013_millisecond_timestamps.down.sql │ │ │ │ ├── 000013_millisecond_timestamps.up.sql │ │ │ │ ├── 000014_add_not_null_constraint.down.sql │ │ │ │ ├── 000014_add_not_null_constraint.up.sql │ │ │ │ ├── 000015_blocks_history_no_nulls.down.sql │ │ │ │ ├── 000015_blocks_history_no_nulls.up.sql │ │ │ │ ├── 000016_subscriptions_table.down.sql │ │ │ │ ├── 000016_subscriptions_table.up.sql │ │ │ │ ├── 000017_add_file_info.down.sql │ │ │ │ ├── 000017_add_file_info.up.sql │ │ │ │ ├── 000018_add_teams_and_boards.down.sql │ │ │ │ ├── 000018_add_teams_and_boards.up.sql │ │ │ │ ├── 000019_populate_categories.down.sql │ │ │ │ ├── 000019_populate_categories.up.sql │ │ │ │ ├── 000020_populate_category_blocks.down.sql │ │ │ │ ├── 000020_populate_category_blocks.up.sql │ │ │ │ ├── 000021_create_boards_members_history.down.sql │ │ │ │ ├── 000021_create_boards_members_history.up.sql │ │ │ │ ├── 000022_create_default_board_role.down.sql │ │ │ │ ├── 000022_create_default_board_role.up.sql │ │ │ │ ├── 000023_persist_category_collapsed_state.down.sql │ │ │ │ ├── 000023_persist_category_collapsed_state.up.sql │ │ │ │ ├── 000024_mark_existsing_categories_collapsed.down.sql │ │ │ │ ├── 000024_mark_existsing_categories_collapsed.up.sql │ │ │ │ ├── 000025_indexes_update.down.sql │ │ │ │ ├── 000025_indexes_update.up.sql │ │ │ │ ├── 000026_create_preferences_table.down.sql │ │ │ │ ├── 000026_create_preferences_table.up.sql │ │ │ │ ├── 000027_migrate_user_props_to_preferences.down.sql │ │ │ │ ├── 000027_migrate_user_props_to_preferences.up.sql │ │ │ │ ├── 000028_remove_template_channel_link.down.sql │ │ │ │ ├── 000028_remove_template_channel_link.up.sql │ │ │ │ ├── 000029_add_category_type_field.down.sql │ │ │ │ ├── 000029_add_category_type_field.up.sql │ │ │ │ ├── 000030_add_category_sort_order.down.sql │ │ │ │ ├── 000030_add_category_sort_order.up.sql │ │ │ │ ├── 000031_add_category_boards_sort_order.down.sql │ │ │ │ ├── 000031_add_category_boards_sort_order.up.sql │ │ │ │ ├── 000032_move_boards_category_to_end.down.sql │ │ │ │ ├── 000032_move_boards_category_to_end.up.sql │ │ │ │ ├── 000033_remove_deleted_category_boards.down.sql │ │ │ │ ├── 000033_remove_deleted_category_boards.up.sql │ │ │ │ ├── 000034_category_boards_remove_unused_delete_at_column.down.sql │ │ │ │ ├── 000034_category_boards_remove_unused_delete_at_column.up.sql │ │ │ │ ├── 000035_add_hidden_board_column.down.sql │ │ │ │ ├── 000035_add_hidden_board_column.up.sql │ │ │ │ ├── 000036_category_board_add_unique_constraint.down.sql │ │ │ │ ├── 000036_category_board_add_unique_constraint.up.sql │ │ │ │ ├── 000037_hidden_boards_from_preferences.down.sql │ │ │ │ ├── 000037_hidden_boards_from_preferences.up.sql │ │ │ │ ├── 000038_delete_hiddenBoardIDs_from_preferences.down.sql │ │ │ │ ├── 000038_delete_hiddenBoardIDs_from_preferences.up.sql │ │ │ │ ├── 000039_add_path_to_file_info.down.sql │ │ │ │ ├── 000039_add_path_to_file_info.up.sql │ │ │ │ ├── 000040_fix_fileinfo_soft_deletes.down.sql │ │ │ │ ├── 000040_fix_fileinfo_soft_deletes.up.sql │ │ │ │ └── README.md │ │ │ ├── migrationstests │ │ │ │ ├── boards_migrator_test.go │ │ │ │ ├── de_duplicate_category_boards_migration_test.go │ │ │ │ ├── fixtures │ │ │ │ │ ├── deletedMembershipBoardsMigrationFixtures.sql │ │ │ │ │ ├── test18AddTeamsAndBoardsSQLMigrationFixtures.sql │ │ │ │ │ ├── test27MigrateUserPropsToPreferences.sql │ │ │ │ │ ├── test28RemoveTemplateChannelLink.sql │ │ │ │ │ ├── test33_with_deleted_data.sql │ │ │ │ │ ├── test33_with_no_deleted_data.sql │ │ │ │ │ ├── test34_drop_delete_at_column.sql │ │ │ │ │ ├── test35_add_hidden_column.sql │ │ │ │ │ ├── test36_add_unique_constraint.sql │ │ │ │ │ ├── test37_valid_data.sql │ │ │ │ │ ├── test37_valid_data_no_hidden_boards.sql │ │ │ │ │ ├── test37_valid_data_preference_but_no_hidden_board.sql │ │ │ │ │ ├── test37_valid_data_sqlite.sql │ │ │ │ │ ├── test37_valid_data_sqlite_preference_but_no_hidden_board.sql │ │ │ │ │ ├── test38_add_plugin_preferences.sql │ │ │ │ │ ├── test38_add_standalone_preferences.sql │ │ │ │ │ ├── test40FixFileinfoSoftDeletes.sql │ │ │ │ │ └── testDeDuplicateCategoryBoardsMigration.sql │ │ │ │ ├── helpers_test.go │ │ │ │ ├── migrate_34_test.go │ │ │ │ ├── migration35_test.go │ │ │ │ ├── migration36_test.go │ │ │ │ ├── migration37_test.go │ │ │ │ ├── migration38_test.go │ │ │ │ ├── migration_27_test.go │ │ │ │ ├── migration_28_test.go │ │ │ │ └── migration_33_test.go │ │ │ ├── notificationhints.go │ │ │ ├── params.go │ │ │ ├── public_methods.go │ │ │ ├── schema_table_migration.go │ │ │ ├── schema_table_migration_test.go │ │ │ ├── session.go │ │ │ ├── sharing.go │ │ │ ├── sqlite.go │ │ │ ├── sqlstore.go │ │ │ ├── sqlstore_test.go │ │ │ ├── subscriptions.go │ │ │ ├── system.go │ │ │ ├── team.go │ │ │ ├── templates.go │ │ │ ├── user.go │ │ │ └── util.go │ │ ├── store.go │ │ └── storetests │ │ │ ├── blocks.go │ │ │ ├── boards.go │ │ │ ├── boards_and_blocks.go │ │ │ ├── category.go │ │ │ ├── categoryBoards.go │ │ │ ├── cloud.go │ │ │ ├── compliance.go │ │ │ ├── data_retention.go │ │ │ ├── files.go │ │ │ ├── helpers.go │ │ │ ├── notificationhints.go │ │ │ ├── session.go │ │ │ ├── sharing.go │ │ │ ├── subscriptions.go │ │ │ ├── system.go │ │ │ ├── teams.go │ │ │ ├── users.go │ │ │ └── util.go │ ├── telemetry │ │ ├── mocks │ │ │ └── ServerIface.go │ │ ├── telemetry.go │ │ └── telemetry_test.go │ └── webhook │ │ ├── webhook.go │ │ └── webhook_test.go ├── swagger │ ├── README.md │ ├── docs │ │ └── html │ │ │ ├── .openapi-generator-ignore │ │ │ ├── .openapi-generator │ │ │ └── VERSION │ │ │ └── index.html │ └── swagger.yml ├── utils │ ├── callbackqueue.go │ ├── callbackqueue_test.go │ ├── debug.go │ ├── links.go │ ├── testUtils.go │ └── utils.go ├── web │ ├── webserver.go │ └── webserver_test.go └── ws │ ├── adapter.go │ ├── common.go │ ├── helpers_test.go │ ├── mocks │ ├── mockpluginapi.go │ └── mockstore.go │ ├── plugin_adapter.go │ ├── plugin_adapter_client.go │ ├── plugin_adapter_cluster.go │ ├── plugin_adapter_test.go │ ├── server.go │ └── server_test.go ├── webapp ├── .eslintignore ├── .eslintrc.json ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .stylelintrc.json ├── NOTICE.txt ├── __mocks__ │ ├── fileMock.js │ └── styleMock.js ├── cypress.json ├── cypress │ ├── config.json │ ├── global.d.ts │ ├── integration │ │ ├── cardBadges.ts │ │ ├── cardURLProperty.ts │ │ ├── createBoard.ts │ │ ├── groupByProperty.ts │ │ ├── loginActions.ts │ │ └── manageGroups.ts │ ├── plugins │ │ └── index.js │ ├── support │ │ ├── api_commands.ts │ │ ├── index.ts │ │ └── ui_commands.ts │ └── tsconfig.json ├── html-templates │ ├── deveditor.ejs │ └── page.ejs ├── i18n │ ├── ar.json │ ├── ars.json │ ├── ca.json │ ├── de.json │ ├── el.json │ ├── en.json │ ├── en_AU.json │ ├── es.json │ ├── et.json │ ├── fa.json │ ├── fr.json │ ├── he.json │ ├── hr.json │ ├── hu.json │ ├── id.json │ ├── it.json │ ├── ja.json │ ├── ka.json │ ├── kab.json │ ├── kk.json │ ├── ko.json │ ├── lt.json │ ├── ml.json │ ├── nb_NO.json │ ├── nl.json │ ├── oc.json │ ├── pl.json │ ├── pt.json │ ├── pt_BR.json │ ├── ru.json │ ├── sk.json │ ├── sl.json │ ├── sv.json │ ├── tr.json │ ├── uk.json │ ├── vi.json │ ├── zh_Hans.json │ └── zh_Hant.json ├── package-lock.json ├── package.json ├── src │ ├── app.tsx │ ├── archiver.ts │ ├── blockIcons.ts │ ├── blocks │ │ ├── __snapshots__ │ │ │ ├── block.test.ts.snap │ │ │ └── board.test.ts.snap │ │ ├── attachmentBlock.tsx │ │ ├── block.test.ts │ │ ├── block.ts │ │ ├── board.test.ts │ │ ├── board.ts │ │ ├── boardView.test.ts │ │ ├── boardView.ts │ │ ├── card.ts │ │ ├── checkboxBlock.ts │ │ ├── commentBlock.ts │ │ ├── contentBlock.ts │ │ ├── dividerBlock.ts │ │ ├── filterClause.test.ts │ │ ├── filterClause.ts │ │ ├── filterGroup.ts │ │ ├── h1Block.tsx │ │ ├── h2Block.tsx │ │ ├── h3Block.tsx │ │ ├── imageBlock.ts │ │ ├── sharing.ts │ │ ├── team.ts │ │ ├── textBlock.ts │ │ └── workspace.ts │ ├── boardCloudLimits │ │ └── index.ts │ ├── boardUtils.ts │ ├── boardsCloudLimits │ │ └── index.ts │ ├── cardFilter.test.ts │ ├── cardFilter.ts │ ├── components │ │ ├── __snapshots__ │ │ │ ├── addContentMenuItem.test.tsx.snap │ │ │ ├── blockIconSelector.test.tsx.snap │ │ │ ├── cardBadges.test.tsx.snap │ │ │ ├── cardDialog.test.tsx.snap │ │ │ ├── centerPanel.test.tsx.snap │ │ │ ├── confirmAddUserForNotifications.test.tsx.snap │ │ │ ├── confirmationDialogBox.test.tsx.snap │ │ │ ├── contentBlock.test.tsx.snap │ │ │ ├── dialog.test.tsx.snap │ │ │ ├── flashMessages.test.tsx.snap │ │ │ ├── markdownEditor.test.tsx.snap │ │ │ ├── modal.test.tsx.snap │ │ │ ├── personSelector.test.tsx.snap │ │ │ ├── propertyValueElement.test.tsx.snap │ │ │ ├── rootPortal.test.tsx.snap │ │ │ ├── topBar.test.tsx.snap │ │ │ ├── viewMenu.test.tsx.snap │ │ │ ├── viewTitle.test.tsx.snap │ │ │ └── workspace.test.tsx.snap │ │ ├── addContentMenuItem.test.tsx │ │ ├── addContentMenuItem.tsx │ │ ├── blockIconSelector.test.tsx │ │ ├── blockIconSelector.tsx │ │ ├── blocksEditor │ │ │ ├── __snapshots__ │ │ │ │ ├── blockContent.test.tsx.snap │ │ │ │ ├── blocksEditor.test.tsx.snap │ │ │ │ ├── editor.test.tsx.snap │ │ │ │ └── rootInput.test.tsx.snap │ │ │ ├── blockContent.scss │ │ │ ├── blockContent.test.tsx │ │ │ ├── blockContent.tsx │ │ │ ├── blocks │ │ │ │ ├── attachment │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── attachment.test.tsx.snap │ │ │ │ │ ├── attachment.scss │ │ │ │ │ ├── attachment.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── checkbox │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── checkbox.test.tsx.snap │ │ │ │ │ ├── checkbox.scss │ │ │ │ │ ├── checkbox.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── divider │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── divider.test.tsx.snap │ │ │ │ │ ├── divider.scss │ │ │ │ │ ├── divider.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── h1 │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── h1.test.tsx.snap │ │ │ │ │ ├── h1.scss │ │ │ │ │ ├── h1.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── h2 │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── h2.test.tsx.snap │ │ │ │ │ ├── h2.scss │ │ │ │ │ ├── h2.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── h3 │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── h3.test.tsx.snap │ │ │ │ │ ├── h3.scss │ │ │ │ │ ├── h3.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── image │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── image.test.tsx.snap │ │ │ │ │ ├── image.scss │ │ │ │ │ ├── image.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── list-item │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── list-item.test.tsx.snap │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── list-item.scss │ │ │ │ │ └── list-item.test.tsx │ │ │ │ ├── quote │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── quote.test.tsx.snap │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── quote.scss │ │ │ │ │ └── quote.test.tsx │ │ │ │ ├── text-dev │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── text.scss │ │ │ │ ├── text │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── text.test.tsx.snap │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── text.scss │ │ │ │ │ └── text.test.tsx │ │ │ │ ├── types.tsx │ │ │ │ └── video │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── video.test.tsx.snap │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── video.scss │ │ │ │ │ └── video.test.tsx │ │ │ ├── blocksEditor.test.tsx │ │ │ ├── blocksEditor.tsx │ │ │ ├── devmain.scss │ │ │ ├── devmain.tsx │ │ │ ├── editor.scss │ │ │ ├── editor.test.tsx │ │ │ ├── editor.tsx │ │ │ ├── rootInput.test.tsx │ │ │ └── rootInput.tsx │ │ ├── boardIconSelector.tsx │ │ ├── boardTemplateSelector │ │ │ ├── __snapshots__ │ │ │ │ ├── boardTemplateSelector.test.tsx.snap │ │ │ │ ├── boardTemplateSelectorItem.test.tsx.snap │ │ │ │ └── boardTemplateSelectorPreview.test.tsx.snap │ │ │ ├── boardTemplateSelector.scss │ │ │ ├── boardTemplateSelector.test.tsx │ │ │ ├── boardTemplateSelector.tsx │ │ │ ├── boardTemplateSelectorItem.scss │ │ │ ├── boardTemplateSelectorItem.test.tsx │ │ │ ├── boardTemplateSelectorItem.tsx │ │ │ ├── boardTemplateSelectorPreview.scss │ │ │ ├── boardTemplateSelectorPreview.test.tsx │ │ │ └── boardTemplateSelectorPreview.tsx │ │ ├── boardsSwitcher │ │ │ ├── boardsSwitcher.scss │ │ │ └── boardsSwitcher.tsx │ │ ├── boardsSwitcherDialog │ │ │ ├── __snapshots__ │ │ │ │ └── boardSwitcherDialog.test.tsx.snap │ │ │ ├── boardSwitcherDialog.scss │ │ │ ├── boardSwitcherDialog.test.tsx │ │ │ └── boardSwitcherDialog.tsx │ │ ├── calculations │ │ │ ├── __snapshots__ │ │ │ │ ├── calculation.test.tsx.snap │ │ │ │ └── options.test.tsx.snap │ │ │ ├── calculation.scss │ │ │ ├── calculation.test.tsx │ │ │ ├── calculation.tsx │ │ │ ├── calculations.test.tsx │ │ │ ├── calculations.ts │ │ │ ├── options.test.tsx │ │ │ └── options.tsx │ │ ├── calendar │ │ │ ├── __snapshots__ │ │ │ │ └── fullCalendar.test.tsx.snap │ │ │ ├── fullCalendar.test.tsx │ │ │ ├── fullCalendar.tsx │ │ │ └── fullcalendar.scss │ │ ├── cardActionsMenu │ │ │ ├── __snapshots__ │ │ │ │ └── cardActionsMenu.test.tsx.snap │ │ │ ├── cardActionsMenu.test.tsx │ │ │ ├── cardActionsMenu.tsx │ │ │ ├── cardActionsMenuIcon.scss │ │ │ └── cardActionsMenuIcon.tsx │ │ ├── cardBadges.scss │ │ ├── cardBadges.test.tsx │ │ ├── cardBadges.tsx │ │ ├── cardDetail │ │ │ ├── __snapshots__ │ │ │ │ ├── cardDetail.test.tsx.snap │ │ │ │ ├── cardDetailContents.test.tsx.snap │ │ │ │ ├── cardDetailContentsMenu.test.tsx.snap │ │ │ │ ├── cardDetailProperties.test.tsx.snap │ │ │ │ ├── comment.test.tsx.snap │ │ │ │ └── commentsList.test.tsx.snap │ │ │ ├── attachment.scss │ │ │ ├── attachment.tsx │ │ │ ├── cardDetail.scss │ │ │ ├── cardDetail.test.tsx │ │ │ ├── cardDetail.tsx │ │ │ ├── cardDetailContents.test.tsx │ │ │ ├── cardDetailContents.tsx │ │ │ ├── cardDetailContentsMenu.test.tsx │ │ │ ├── cardDetailContentsMenu.tsx │ │ │ ├── cardDetailContentsUtility.test.ts │ │ │ ├── cardDetailContentsUtility.ts │ │ │ ├── cardDetailContext.tsx │ │ │ ├── cardDetailProperties.test.tsx │ │ │ ├── cardDetailProperties.tsx │ │ │ ├── comment.scss │ │ │ ├── comment.test.tsx │ │ │ ├── comment.tsx │ │ │ ├── commentsList.scss │ │ │ ├── commentsList.test.tsx │ │ │ ├── commentsList.tsx │ │ │ └── imagePaste.tsx │ │ ├── cardDialog.scss │ │ ├── cardDialog.test.tsx │ │ ├── cardDialog.tsx │ │ ├── cardLimitNotification.scss │ │ ├── cardLimitNotification.tsx │ │ ├── centerPanel.scss │ │ ├── centerPanel.test.tsx │ │ ├── centerPanel.tsx │ │ ├── confirmAddUserForNotifications.scss │ │ ├── confirmAddUserForNotifications.test.tsx │ │ ├── confirmAddUserForNotifications.tsx │ │ ├── confirmationDialogBox.scss │ │ ├── confirmationDialogBox.test.tsx │ │ ├── confirmationDialogBox.tsx │ │ ├── content │ │ │ ├── __snapshots__ │ │ │ │ ├── attachmentElement.test.tsx.snap │ │ │ │ ├── checkboxElement.test.tsx.snap │ │ │ │ ├── contentElement.test.tsx.snap │ │ │ │ ├── dividerElement.test.tsx.snap │ │ │ │ ├── imageElement.test.tsx.snap │ │ │ │ └── textElement.test.tsx.snap │ │ │ ├── archivedFile │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── archivedFile.test.tsx.snap │ │ │ │ ├── archivedFile.scss │ │ │ │ ├── archivedFile.test.tsx │ │ │ │ └── archivedFile.tsx │ │ │ ├── attachmentElement.scss │ │ │ ├── attachmentElement.test.tsx │ │ │ ├── attachmentElement.tsx │ │ │ ├── checkboxElement.scss │ │ │ ├── checkboxElement.test.tsx │ │ │ ├── checkboxElement.tsx │ │ │ ├── contentElement.test.tsx │ │ │ ├── contentElement.tsx │ │ │ ├── contentRegistry.test.tsx │ │ │ ├── contentRegistry.tsx │ │ │ ├── dividerElement.scss │ │ │ ├── dividerElement.test.tsx │ │ │ ├── dividerElement.tsx │ │ │ ├── imageElement.test.tsx │ │ │ ├── imageElement.tsx │ │ │ ├── textElement.scss │ │ │ ├── textElement.test.tsx │ │ │ └── textElement.tsx │ │ ├── contentBlock.scss │ │ ├── contentBlock.test.tsx │ │ ├── contentBlock.tsx │ │ ├── createCategory │ │ │ ├── __snapshots__ │ │ │ │ └── createCategory.test.tsx.snap │ │ │ ├── createCategory.scss │ │ │ ├── createCategory.test.tsx │ │ │ └── createCategory.tsx │ │ ├── dialog.scss │ │ ├── dialog.test.tsx │ │ ├── dialog.tsx │ │ ├── flashMessages.scss │ │ ├── flashMessages.test.tsx │ │ ├── flashMessages.tsx │ │ ├── gallery │ │ │ ├── __snapshots__ │ │ │ │ ├── gallery.test.tsx.snap │ │ │ │ └── galleryCard.test.tsx.snap │ │ │ ├── gallery.scss │ │ │ ├── gallery.test.tsx │ │ │ ├── gallery.tsx │ │ │ ├── galleryCard.scss │ │ │ ├── galleryCard.test.tsx │ │ │ └── galleryCard.tsx │ │ ├── globalHeader │ │ │ ├── __snapshots__ │ │ │ │ ├── globalHeader.test.tsx.snap │ │ │ │ └── globalHeaderSettingsMenu.test.tsx.snap │ │ │ ├── globalHeader.scss │ │ │ ├── globalHeader.test.tsx │ │ │ ├── globalHeader.tsx │ │ │ ├── globalHeaderSettingsMenu.scss │ │ │ ├── globalHeaderSettingsMenu.test.tsx │ │ │ └── globalHeaderSettingsMenu.tsx │ │ ├── guestNoBoards.scss │ │ ├── guestNoBoards.tsx │ │ ├── hiddenCardCount │ │ │ ├── hiddenCardCount.scss │ │ │ └── hiddenCardCount.tsx │ │ ├── iconSelector.scss │ │ ├── iconSelector.tsx │ │ ├── kanban │ │ │ ├── __snapshots__ │ │ │ │ ├── kanban.test.tsx.snap │ │ │ │ ├── kanbanCard.test.tsx.snap │ │ │ │ ├── kanbanColumn.test.tsx.snap │ │ │ │ ├── kanbanColumnHeader.test.tsx.snap │ │ │ │ └── kanbanHiddenColumnItem.test.tsx.snap │ │ │ ├── calculation │ │ │ │ ├── __snapshots__ │ │ │ │ │ ├── calculation.test.tsx.snap │ │ │ │ │ ├── calculationOptions.test.tsx.snap │ │ │ │ │ └── kanbanOption.test.tsx.snap │ │ │ │ ├── calculation.scss │ │ │ │ ├── calculation.test.tsx │ │ │ │ ├── calculation.tsx │ │ │ │ ├── calculationOption.scss │ │ │ │ ├── calculationOptions.test.tsx │ │ │ │ ├── calculationOptions.tsx │ │ │ │ ├── kanbanOption.test.tsx │ │ │ │ └── kanbanOption.tsx │ │ │ ├── kanban.scss │ │ │ ├── kanban.test.tsx │ │ │ ├── kanban.tsx │ │ │ ├── kanbanCard.scss │ │ │ ├── kanbanCard.test.tsx │ │ │ ├── kanbanCard.tsx │ │ │ ├── kanbanColumn.scss │ │ │ ├── kanbanColumn.test.tsx │ │ │ ├── kanbanColumn.tsx │ │ │ ├── kanbanColumnHeader.test.tsx │ │ │ ├── kanbanColumnHeader.tsx │ │ │ ├── kanbanHiddenColumnItem.test.tsx │ │ │ └── kanbanHiddenColumnItem.tsx │ │ ├── live-markdown-plugin │ │ │ ├── block-types │ │ │ │ ├── codeBlockStrategy.ts │ │ │ │ └── headingBlockStrategy.ts │ │ │ ├── inline-styles │ │ │ │ ├── boldStyleStrategy.ts │ │ │ │ ├── headingDelimiterStyleStrategy.ts │ │ │ │ ├── inlineCodeStyleStrategy.ts │ │ │ │ ├── italicStyleStrategy.ts │ │ │ │ ├── olDelimiterStyleStrategy.ts │ │ │ │ ├── quoteStyleStrategy.ts │ │ │ │ ├── strikethroughStyleStrategy.ts │ │ │ │ └── ulDelimiterStyleStrategy.ts │ │ │ ├── liveMarkdownPlugin.ts │ │ │ ├── pluginStrategy.ts │ │ │ └── utils │ │ │ │ └── findRangesWithRegex.ts │ │ ├── markdownEditor.scss │ │ ├── markdownEditor.test.tsx │ │ ├── markdownEditor.tsx │ │ ├── markdownEditorInput │ │ │ ├── entryComponent │ │ │ │ ├── entryComponent.scss │ │ │ │ └── entryComponent.tsx │ │ │ ├── markdownEditorInput.scss │ │ │ └── markdownEditorInput.tsx │ │ ├── messages │ │ │ ├── versionMessage.scss │ │ │ ├── versionMessage.test.tsx │ │ │ └── versionMessage.tsx │ │ ├── modal.scss │ │ ├── modal.test.tsx │ │ ├── modal.tsx │ │ ├── modalWrapper.scss │ │ ├── modalWrapper.tsx │ │ ├── newVersionBanner.scss │ │ ├── newVersionBanner.tsx │ │ ├── onboardingTour │ │ │ ├── addComments │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── addComments.test.tsx.snap │ │ │ │ ├── addComments.test.tsx │ │ │ │ ├── addComments.tsx │ │ │ │ └── add_comments.scss │ │ │ ├── addDescription │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── addDescription.test.tsx.snap │ │ │ │ ├── addDescription.test.tsx │ │ │ │ ├── add_description.scss │ │ │ │ └── add_description.tsx │ │ │ ├── addProperties │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── addProperties.test.tsx.snap │ │ │ │ ├── addProperties.test.tsx │ │ │ │ ├── add_properties.scss │ │ │ │ └── add_properties.tsx │ │ │ ├── addView │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── addView.test.tsx.snap │ │ │ │ ├── addView.test.tsx │ │ │ │ ├── add_view.scss │ │ │ │ └── add_view.tsx │ │ │ ├── copyLink │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── copyLink.test.tsx.snap │ │ │ │ ├── copyLink.test.tsx │ │ │ │ ├── copy_link.scss │ │ │ │ └── copy_link.tsx │ │ │ ├── index.ts │ │ │ ├── manageCategories │ │ │ │ ├── manageCategories.scss │ │ │ │ └── manageCategories.tsx │ │ │ ├── openCard │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── openCard.test.tsx.snap │ │ │ │ ├── openCard.test.tsx │ │ │ │ ├── open_card.scss │ │ │ │ └── open_card.tsx │ │ │ ├── searchForBoards │ │ │ │ ├── searchForBoards.scss │ │ │ │ └── searchForBoards.tsx │ │ │ ├── shareBoard │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── shareBoard.test.tsx.snap │ │ │ │ ├── shareBoard.scss │ │ │ │ ├── shareBoard.test.tsx │ │ │ │ └── shareBoard.tsx │ │ │ ├── sidebarCategories │ │ │ │ ├── sidebarCategories.scss │ │ │ │ └── sidebarCategories.tsx │ │ │ └── tourTipRenderer │ │ │ │ └── tourTipRenderer.tsx │ │ ├── permissions │ │ │ ├── __snapshots__ │ │ │ │ └── boardPermissionGate.test.tsx.snap │ │ │ ├── boardPermissionGate.test.tsx │ │ │ └── boardPermissionGate.tsx │ │ ├── personSelector.scss │ │ ├── personSelector.test.tsx │ │ ├── personSelector.tsx │ │ ├── propertyValueElement.test.tsx │ │ ├── propertyValueElement.tsx │ │ ├── pulsating_dot │ │ │ ├── index.tsx │ │ │ └── pulsating_dot.scss │ │ ├── rootPortal.test.tsx │ │ ├── rootPortal.tsx │ │ ├── searchDialog │ │ │ ├── searchDialog.scss │ │ │ └── searchDialog.tsx │ │ ├── shareBoard │ │ │ ├── __snapshots__ │ │ │ │ ├── shareBoard.test.tsx.snap │ │ │ │ ├── shareBoardButton.test.tsx.snap │ │ │ │ ├── shareBoardLoginButton.test.tsx.snap │ │ │ │ ├── teamPermissionsRow.test.tsx.snap │ │ │ │ └── userPermissionsRow.test.tsx.snap │ │ │ ├── shareBoard.scss │ │ │ ├── shareBoard.test.tsx │ │ │ ├── shareBoard.tsx │ │ │ ├── shareBoardButton.scss │ │ │ ├── shareBoardButton.test.tsx │ │ │ ├── shareBoardButton.tsx │ │ │ ├── shareBoardLoginButton.scss │ │ │ ├── shareBoardLoginButton.test.tsx │ │ │ ├── shareBoardLoginButton.tsx │ │ │ ├── teamPermissionsRow.test.tsx │ │ │ ├── teamPermissionsRow.tsx │ │ │ ├── userPermissionsRow.test.tsx │ │ │ └── userPermissionsRow.tsx │ │ ├── sidebar │ │ │ ├── __snapshots__ │ │ │ │ ├── deleteBoardDialog.test.tsx.snap │ │ │ │ ├── registrationLink.test.tsx.snap │ │ │ │ ├── sidebar.test.tsx.snap │ │ │ │ ├── sidebarBoardItem.test.tsx.snap │ │ │ │ ├── sidebarCategory.test.tsx.snap │ │ │ │ └── sidebarSettingsMenu.test.tsx.snap │ │ │ ├── deleteBoardDialog.scss │ │ │ ├── deleteBoardDialog.test.tsx │ │ │ ├── deleteBoardDialog.tsx │ │ │ ├── registrationLink.scss │ │ │ ├── registrationLink.test.tsx │ │ │ ├── registrationLink.tsx │ │ │ ├── sidebar.scss │ │ │ ├── sidebar.test.tsx │ │ │ ├── sidebar.tsx │ │ │ ├── sidebarBoardItem.scss │ │ │ ├── sidebarBoardItem.test.tsx │ │ │ ├── sidebarBoardItem.tsx │ │ │ ├── sidebarCategory.scss │ │ │ ├── sidebarCategory.test.tsx │ │ │ ├── sidebarCategory.tsx │ │ │ ├── sidebarSettingsMenu.scss │ │ │ ├── sidebarSettingsMenu.test.tsx │ │ │ ├── sidebarSettingsMenu.tsx │ │ │ ├── sidebarUserMenu.scss │ │ │ └── sidebarUserMenu.tsx │ │ ├── table │ │ │ ├── __snapshots__ │ │ │ │ ├── table.test.tsx.snap │ │ │ │ ├── tableGroupHeaderRow.test.tsx.snap │ │ │ │ ├── tableHeader.test.tsx.snap │ │ │ │ ├── tableHeaderMenu.test.tsx.snap │ │ │ │ ├── tableHeaders.test.tsx.snap │ │ │ │ ├── tableRow.test.tsx.snap │ │ │ │ └── tableRows.test.tsx.snap │ │ │ ├── calculation │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── calculationRow.test.tsx.snap │ │ │ │ ├── calculationRow.scss │ │ │ │ ├── calculationRow.test.tsx │ │ │ │ ├── calculationRow.tsx │ │ │ │ └── tableCalculationOptions.tsx │ │ │ ├── horizontalGrip.scss │ │ │ ├── horizontalGrip.tsx │ │ │ ├── table.scss │ │ │ ├── table.test.tsx │ │ │ ├── table.tsx │ │ │ ├── tableColumnResizeContext.tsx │ │ │ ├── tableGroup.tsx │ │ │ ├── tableGroupHeaderRow.test.tsx │ │ │ ├── tableGroupHeaderRow.tsx │ │ │ ├── tableHeader.test.tsx │ │ │ ├── tableHeader.tsx │ │ │ ├── tableHeaderMenu.test.tsx │ │ │ ├── tableHeaderMenu.tsx │ │ │ ├── tableHeaders.test.tsx │ │ │ ├── tableHeaders.tsx │ │ │ ├── tableRow.scss │ │ │ ├── tableRow.test.tsx │ │ │ ├── tableRow.tsx │ │ │ ├── tableRows.test.tsx │ │ │ └── tableRows.tsx │ │ ├── topBar.scss │ │ ├── topBar.test.tsx │ │ ├── topBar.tsx │ │ ├── tutorial_tour_tip │ │ │ ├── hooks.ts │ │ │ ├── tutorial_tour_tip.scss │ │ │ ├── tutorial_tour_tip.tsx │ │ │ ├── tutorial_tour_tip_backdrop.tsx │ │ │ ├── tutorial_tour_tip_manager.tsx │ │ │ └── useElementAvailable.ts │ │ ├── viewHeader │ │ │ ├── __snapshots__ │ │ │ │ ├── dateFilter.test.tsx.snap │ │ │ │ ├── emptyCardButton.test.tsx.snap │ │ │ │ ├── filterComponent.test.tsx.snap │ │ │ │ ├── filterEntry.test.tsx.snap │ │ │ │ ├── filterValue.test.tsx.snap │ │ │ │ ├── newCardButton.test.tsx.snap │ │ │ │ ├── newCardButtonTemplateItem.test.tsx.snap │ │ │ │ ├── viewHeader.test.tsx.snap │ │ │ │ ├── viewHeaderActionsMenu.test.tsx.snap │ │ │ │ ├── viewHeaderGroupByMenu.test.tsx.snap │ │ │ │ ├── viewHeaderPropertiesMenu.test.tsx.snap │ │ │ │ ├── viewHeaderSearch.test.tsx.snap │ │ │ │ └── viewHeaderSortMenu.test.tsx.snap │ │ │ ├── dateFilter.scss │ │ │ ├── dateFilter.test.tsx │ │ │ ├── dateFilter.tsx │ │ │ ├── emptyCardButton.test.tsx │ │ │ ├── emptyCardButton.tsx │ │ │ ├── filterComponent.scss │ │ │ ├── filterComponent.test.tsx │ │ │ ├── filterComponent.tsx │ │ │ ├── filterEntry.scss │ │ │ ├── filterEntry.test.tsx │ │ │ ├── filterEntry.tsx │ │ │ ├── filterValue.scss │ │ │ ├── filterValue.test.tsx │ │ │ ├── filterValue.tsx │ │ │ ├── multiperson.scss │ │ │ ├── multipersonFilterValue.tsx │ │ │ ├── newCardButton.test.tsx │ │ │ ├── newCardButton.tsx │ │ │ ├── newCardButtonTemplateItem.test.tsx │ │ │ ├── newCardButtonTemplateItem.tsx │ │ │ ├── viewHeader.scss │ │ │ ├── viewHeader.test.tsx │ │ │ ├── viewHeader.tsx │ │ │ ├── viewHeaderActionsMenu.test.tsx │ │ │ ├── viewHeaderActionsMenu.tsx │ │ │ ├── viewHeaderDisplayByMenu.tsx │ │ │ ├── viewHeaderGroupByMenu.test.tsx │ │ │ ├── viewHeaderGroupByMenu.tsx │ │ │ ├── viewHeaderPropertiesMenu.test.tsx │ │ │ ├── viewHeaderPropertiesMenu.tsx │ │ │ ├── viewHeaderSearch.test.tsx │ │ │ ├── viewHeaderSearch.tsx │ │ │ ├── viewHeaderSortMenu.test.tsx │ │ │ └── viewHeaderSortMenu.tsx │ │ ├── viewMenu.scss │ │ ├── viewMenu.test.tsx │ │ ├── viewMenu.tsx │ │ ├── viewTitle.scss │ │ ├── viewTitle.test.tsx │ │ ├── viewTitle.tsx │ │ ├── withWebSockets.tsx │ │ ├── workspace.scss │ │ ├── workspace.test.tsx │ │ └── workspace.tsx │ ├── config │ │ └── clientConfig.ts │ ├── constants.ts │ ├── csvExporter.ts │ ├── emojiList.ts │ ├── errors.ts │ ├── file.ts │ ├── fileIcons.ts │ ├── fonts │ │ └── metropolis │ │ │ ├── Metropolis-Light.woff2 │ │ │ ├── Metropolis-LightItalic.woff2 │ │ │ ├── Metropolis-Regular.woff2 │ │ │ ├── Metropolis-RegularItalic.woff2 │ │ │ ├── Metropolis-SemiBold.woff2 │ │ │ └── Metropolis-SemiBoldItalic.woff2 │ ├── hooks │ │ ├── permissions.tsx │ │ ├── sortable.tsx │ │ ├── useGetAllTemplates.ts │ │ └── websockets.tsx │ ├── i18n.tsx │ ├── insights │ │ └── index.ts │ ├── main.tsx │ ├── mutator.test.ts │ ├── mutator.ts │ ├── nativeApp.ts │ ├── octoClient.test.ts │ ├── octoClient.ts │ ├── octoUtils.test.ts │ ├── octoUtils.tsx │ ├── onboardingTour │ │ └── index.ts │ ├── pages │ │ ├── boardPage │ │ │ ├── backwardCompatibilityQueryParamsRedirect.tsx │ │ │ ├── boardPage.scss │ │ │ ├── boardPage.tsx │ │ │ ├── setWindowTitleAndIcon.tsx │ │ │ ├── teamToBoardAndViewRedirect.tsx │ │ │ ├── undoRedoHotKeys.tsx │ │ │ └── websocketConnection.tsx │ │ ├── changePasswordPage.scss │ │ ├── changePasswordPage.tsx │ │ ├── errorPage.scss │ │ ├── errorPage.tsx │ │ ├── loginPage.scss │ │ ├── loginPage.tsx │ │ ├── registerPage.scss │ │ ├── registerPage.tsx │ │ └── welcome │ │ │ ├── __snapshots__ │ │ │ └── welcomePage.test.tsx.snap │ │ │ ├── welcomePage.scss │ │ │ ├── welcomePage.test.tsx │ │ │ └── welcomePage.tsx │ ├── properties │ │ ├── baseTextEditor.tsx │ │ ├── checkbox │ │ │ ├── checkbox.tsx │ │ │ └── property.tsx │ │ ├── createdBy │ │ │ ├── __snapshots__ │ │ │ │ └── createdBy.test.tsx.snap │ │ │ ├── createdBy.test.tsx │ │ │ ├── createdBy.tsx │ │ │ └── property.tsx │ │ ├── createdTime │ │ │ ├── createdTime.scss │ │ │ ├── createdTime.tsx │ │ │ └── property.tsx │ │ ├── date │ │ │ ├── __snapshots__ │ │ │ │ └── date.test.tsx.snap │ │ │ ├── date.scss │ │ │ ├── date.test.tsx │ │ │ ├── date.tsx │ │ │ └── property.tsx │ │ ├── email │ │ │ ├── email.tsx │ │ │ └── property.tsx │ │ ├── index.tsx │ │ ├── multiperson │ │ │ ├── __snapshots__ │ │ │ │ └── multiperson.test.tsx.snap │ │ │ ├── multiperson.test.tsx │ │ │ ├── multiperson.tsx │ │ │ └── property.tsx │ │ ├── multiselect │ │ │ ├── __snapshots__ │ │ │ │ └── multiselect.test.tsx.snap │ │ │ ├── multiselect.test.tsx │ │ │ ├── multiselect.tsx │ │ │ └── property.tsx │ │ ├── number │ │ │ ├── __snapshots__ │ │ │ │ └── number.test.tsx.snap │ │ │ ├── number.test.tsx │ │ │ ├── number.tsx │ │ │ └── property.tsx │ │ ├── person │ │ │ ├── __snapshots__ │ │ │ │ ├── confirmPerson.test.tsx.snap │ │ │ │ └── person.test.tsx.snap │ │ │ ├── confirmPerson.test.tsx │ │ │ ├── confirmPerson.tsx │ │ │ ├── person.test.tsx │ │ │ ├── person.tsx │ │ │ └── property.tsx │ │ ├── phone │ │ │ ├── phone.tsx │ │ │ └── property.tsx │ │ ├── select │ │ │ ├── __snapshots__ │ │ │ │ └── select.test.tsx.snap │ │ │ ├── property.tsx │ │ │ ├── select.test.tsx │ │ │ └── select.tsx │ │ ├── text │ │ │ ├── property.tsx │ │ │ └── text.tsx │ │ ├── types.tsx │ │ ├── unknown │ │ │ └── property.tsx │ │ ├── updatedBy │ │ │ ├── __snapshots__ │ │ │ │ └── updatedBy.test.tsx.snap │ │ │ ├── property.tsx │ │ │ ├── updatedBy.scss │ │ │ ├── updatedBy.test.tsx │ │ │ └── updatedBy.tsx │ │ ├── updatedTime │ │ │ ├── __snapshots__ │ │ │ │ └── updatedTime.test.tsx.snap │ │ │ ├── property.tsx │ │ │ ├── updatedTime.scss │ │ │ ├── updatedTime.test.tsx │ │ │ └── updatedTime.tsx │ │ └── url │ │ │ ├── __snapshots__ │ │ │ └── url.test.tsx.snap │ │ │ ├── property.tsx │ │ │ ├── url.scss │ │ │ ├── url.test.tsx │ │ │ └── url.tsx │ ├── route.tsx │ ├── router.tsx │ ├── statistics │ │ └── index.ts │ ├── store │ │ ├── attachments.ts │ │ ├── boards.ts │ │ ├── cards.ts │ │ ├── channels.ts │ │ ├── clientConfig.ts │ │ ├── comments.ts │ │ ├── contents.ts │ │ ├── globalError.ts │ │ ├── globalTemplates.ts │ │ ├── hooks.ts │ │ ├── index.ts │ │ ├── initialLoad.ts │ │ ├── language.ts │ │ ├── limits.ts │ │ ├── searchText.ts │ │ ├── sidebar.ts │ │ ├── teams.ts │ │ ├── users.ts │ │ └── views.ts │ ├── styles │ │ ├── _markdown.scss │ │ ├── _modifiers.scss │ │ ├── _typography.scss │ │ ├── _z-index.scss │ │ ├── focalboard-variables.scss │ │ ├── labels.scss │ │ ├── main.scss │ │ ├── shared-variables.scss │ │ └── variables.scss │ ├── svg │ │ ├── card-skeleton.tsx │ │ ├── error-illustration.tsx │ │ └── search-illustration.tsx │ ├── telemetry │ │ ├── telemetry.ts │ │ ├── telemetryClient.test.ts │ │ └── telemetryClient.ts │ ├── test │ │ ├── fetchMock.ts │ │ └── testBlockFactory.ts │ ├── testUtils.tsx │ ├── theme.ts │ ├── tsconfig.json │ ├── types │ │ ├── images.d.ts │ │ └── index.d.ts │ ├── undoManager.test.ts │ ├── undomanager.ts │ ├── user.tsx │ ├── userSettings.ts │ ├── utils.test.ts │ ├── utils.ts │ ├── widgets │ │ ├── __snapshots__ │ │ │ ├── guestBadge.test.tsx.snap │ │ │ └── propertyMenu.test.tsx.snap │ │ ├── adminBadge │ │ │ ├── __snapshots__ │ │ │ │ └── adminBadge.test.tsx.snap │ │ │ ├── adminBadge.scss │ │ │ ├── adminBadge.test.tsx │ │ │ └── adminBadge.tsx │ │ ├── buttons │ │ │ ├── button.scss │ │ │ ├── button.tsx │ │ │ ├── buttonWithMenu.scss │ │ │ ├── buttonWithMenu.tsx │ │ │ ├── iconButton.scss │ │ │ └── iconButton.tsx │ │ ├── editable.scss │ │ ├── editable.tsx │ │ ├── editableArea.scss │ │ ├── editableArea.tsx │ │ ├── editableDayPicker.scss │ │ ├── editableDayPicker.tsx │ │ ├── emojiPicker.scss │ │ ├── emojiPicker.tsx │ │ ├── guestBadge.scss │ │ ├── guestBadge.test.tsx │ │ ├── guestBadge.tsx │ │ ├── icons │ │ │ ├── HandRight.tsx │ │ │ ├── Link.tsx │ │ │ ├── add.scss │ │ │ ├── add.tsx │ │ │ ├── alert.tsx │ │ │ ├── apps.tsx │ │ │ ├── board.scss │ │ │ ├── board.tsx │ │ │ ├── brokenFile.tsx │ │ │ ├── calendar.scss │ │ │ ├── calendar.tsx │ │ │ ├── card.scss │ │ │ ├── card.tsx │ │ │ ├── check.scss │ │ │ ├── check.tsx │ │ │ ├── checkIcon.tsx │ │ │ ├── chevronDown.tsx │ │ │ ├── chevronRight.tsx │ │ │ ├── chevronUp.tsx │ │ │ ├── close.tsx │ │ │ ├── closeCircle.tsx │ │ │ ├── compassIcon.tsx │ │ │ ├── delete.scss │ │ │ ├── delete.tsx │ │ │ ├── disclosureTriangle.scss │ │ │ ├── disclosureTriangle.tsx │ │ │ ├── divider.scss │ │ │ ├── divider.tsx │ │ │ ├── dot.scss │ │ │ ├── dot.tsx │ │ │ ├── dropdown.scss │ │ │ ├── dropdown.tsx │ │ │ ├── duplicate.scss │ │ │ ├── duplicate.tsx │ │ │ ├── edit.tsx │ │ │ ├── emoji.scss │ │ │ ├── emoji.tsx │ │ │ ├── focalboard_logo.scss │ │ │ ├── focalboard_logo.tsx │ │ │ ├── folder.tsx │ │ │ ├── gallery.scss │ │ │ ├── gallery.tsx │ │ │ ├── globe.tsx │ │ │ ├── grip.scss │ │ │ ├── grip.tsx │ │ │ ├── hamburger.scss │ │ │ ├── hamburger.tsx │ │ │ ├── help.scss │ │ │ ├── help.tsx │ │ │ ├── hide.scss │ │ │ ├── hide.tsx │ │ │ ├── hideSidebar.scss │ │ │ ├── hideSidebar.tsx │ │ │ ├── image.scss │ │ │ ├── image.tsx │ │ │ ├── link.scss │ │ │ ├── lockOutline.tsx │ │ │ ├── logo.scss │ │ │ ├── logo.tsx │ │ │ ├── logoWithName.scss │ │ │ ├── logoWithName.tsx │ │ │ ├── logoWithNameWhite.scss │ │ │ ├── logoWithNameWhite.tsx │ │ │ ├── message.tsx │ │ │ ├── newFolder.tsx │ │ │ ├── options.scss │ │ │ ├── options.tsx │ │ │ ├── random.tsx │ │ │ ├── search.tsx │ │ │ ├── settings.scss │ │ │ ├── settings.tsx │ │ │ ├── show.scss │ │ │ ├── show.tsx │ │ │ ├── showSidebar.scss │ │ │ ├── showSidebar.tsx │ │ │ ├── sortDown.scss │ │ │ ├── sortDown.tsx │ │ │ ├── sortUp.scss │ │ │ ├── sortUp.tsx │ │ │ ├── submenuTriangle.scss │ │ │ ├── submenuTriangle.tsx │ │ │ ├── table.scss │ │ │ ├── table.tsx │ │ │ ├── text.scss │ │ │ ├── text.tsx │ │ │ └── update.tsx │ │ ├── label.scss │ │ ├── label.tsx │ │ ├── menu │ │ │ ├── colorOption.scss │ │ │ ├── colorOption.tsx │ │ │ ├── index.tsx │ │ │ ├── labelOption.scss │ │ │ ├── labelOption.tsx │ │ │ ├── menu.scss │ │ │ ├── menu.tsx │ │ │ ├── menuItem.tsx │ │ │ ├── menuUtil.ts │ │ │ ├── separatorOption.scss │ │ │ ├── separatorOption.tsx │ │ │ ├── subMenuOption.scss │ │ │ ├── subMenuOption.tsx │ │ │ ├── switchOption.tsx │ │ │ ├── textInputOption.tsx │ │ │ └── textOption.tsx │ │ ├── menuWrapper.scss │ │ ├── menuWrapper.tsx │ │ ├── notificationBox │ │ │ ├── __snapshots__ │ │ │ │ └── notificationBox.test.tsx.snap │ │ │ ├── notificationBox.scss │ │ │ ├── notificationBox.test.tsx │ │ │ └── notificationBox.tsx │ │ ├── propertyMenu.scss │ │ ├── propertyMenu.test.tsx │ │ ├── propertyMenu.tsx │ │ ├── switch.scss │ │ ├── switch.tsx │ │ ├── tooltip.scss │ │ ├── tooltip.tsx │ │ ├── valueSelector.scss │ │ └── valueSelector.tsx │ └── wsclient.ts ├── static │ ├── addDescription.png │ ├── addProperty.gif │ ├── app-bar-icon.png │ ├── boards-screenshots.png │ ├── boards-welcome-small.png │ ├── boards-welcome.png │ ├── changeViews.gif │ ├── comment.gif │ ├── copyLink.gif │ ├── emoji_spirit.png │ ├── favicon.svg │ ├── onboardingBg.jpg │ ├── share.gif │ └── upgrade.png ├── tsconfig.json ├── tslint.json ├── webpack.common.js ├── webpack.dev.js ├── webpack.editor.js └── webpack.prod.js ├── website ├── .editorconfig ├── .gitignore ├── Makefile ├── README.md └── site │ ├── .hugo_build.lock │ ├── archetypes │ └── default.md │ ├── config.toml │ ├── content │ ├── blog │ │ ├── 2021-1-7-hello.md │ │ ├── 2021-4-21-Focalboard v0.6.5 release.md │ │ ├── 2021-4-27-Mattermost-Focalboard-early-preview.md │ │ ├── 2021-5-07-meeting-agenda-template.md │ │ ├── 2021-5-13-Focalboard-the-road-to-v1.md │ │ └── 2021-6-18-Mattermost-Focalboard-release.md │ ├── docs │ │ └── personal-edition │ │ │ ├── _index.md │ │ │ ├── desktop.md │ │ │ ├── docker.md │ │ │ ├── ubuntu-upgrade.md │ │ │ └── ubuntu.md │ ├── download │ │ └── index.html │ ├── feedback │ │ └── _index.md │ ├── fwlink │ │ ├── doc-boards.html │ │ ├── feedback-boards.html │ │ ├── feedback-focalboard.html │ │ ├── plugin-setup.html │ │ ├── setup-536.html │ │ ├── v1-focalboard.html │ │ └── websocket-connect-error.html │ └── guide │ │ ├── admin │ │ └── _index.md │ │ ├── server-setup │ │ └── _index.md │ │ ├── user │ │ ├── _index.md │ │ ├── add view.png │ │ ├── all tasks.png │ │ ├── board sidebar menu.png │ │ ├── by status properties.png │ │ ├── by status.png │ │ ├── settings menu.png │ │ ├── share board menu.png │ │ ├── share board.png │ │ └── table header menu.png │ │ └── websocket-errors │ │ └── _index.md │ ├── layouts │ ├── 404.html │ ├── _default │ │ ├── _markup │ │ │ └── render-link.html │ │ ├── list.html │ │ ├── page.html │ │ ├── single.html │ │ └── taxonomy.html │ ├── blog │ │ ├── li.html │ │ ├── list.html │ │ ├── single.html │ │ └── summary.html │ ├── index.html │ ├── indexes │ │ └── tag.html │ ├── partials │ │ ├── blogauthor.html │ │ ├── footer.html │ │ ├── hanchor.html │ │ ├── head.html │ │ ├── hero.html │ │ ├── intro.html │ │ ├── mailinglist.html │ │ ├── nav.html │ │ ├── notification.html │ │ ├── page-edit.html │ │ ├── series_link.html │ │ └── sidebar.html │ └── shortcodes │ │ ├── baseurl.html │ │ ├── bignumber.html │ │ ├── blogurl.html │ │ ├── content.html │ │ ├── md.html │ │ └── note.html │ ├── static │ ├── css │ │ ├── bar.css │ │ ├── bootstrap.min.css │ │ ├── code.css │ │ ├── markdown.css │ │ ├── note.css │ │ ├── partials │ │ │ ├── banners.css │ │ │ ├── base.css │ │ │ ├── blog.css │ │ │ ├── buttons.css │ │ │ ├── fontawesome.css │ │ │ ├── footer.css │ │ │ ├── header.css │ │ │ ├── homepage.css │ │ │ ├── root.css │ │ │ ├── sidebar.css │ │ │ └── template-picker.css │ │ ├── styles.css │ │ └── tabs.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── img │ │ ├── 3d-icons │ │ │ ├── development.svg │ │ │ ├── firstbump.svg │ │ │ ├── gasp.svg │ │ │ ├── handshake.svg │ │ │ ├── raisedhands.svg │ │ │ └── rocket.svg │ │ ├── arrow-right.svg │ │ ├── bgroundedcenter.svg │ │ ├── bgroundedleft.svg │ │ ├── bgroundedright.svg │ │ ├── bullseye.svg │ │ ├── check.svg │ │ ├── contribute-icon.svg │ │ ├── developers-icon.svg │ │ ├── download-icon.svg │ │ ├── extend-icon.svg │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── footer-logo-black.svg │ │ ├── footer-logo.svg │ │ ├── hero.jpg │ │ ├── integrate-icon.svg │ │ ├── logo-w-mattermost.svg │ │ ├── logo-white.svg │ │ ├── logo.svg │ │ ├── mac-app-store-white.svg │ │ ├── mac-app-store.svg │ │ ├── mentioned │ │ │ ├── newstack.png │ │ │ ├── producthunt.png │ │ │ ├── techrepublic.png │ │ │ ├── venturebeat.png │ │ │ └── ycombinator.png │ │ ├── mm-logo-white.svg │ │ ├── mm-logo.svg │ │ ├── ms-app-store.svg │ │ ├── needhelp.svg │ │ ├── roadmap │ │ │ ├── analytics.png │ │ │ ├── card-dependencies.png │ │ │ └── standard-properties.png │ │ ├── search-icon.svg │ │ ├── single-users-icon.svg │ │ ├── tabs │ │ │ └── boards.png │ │ ├── teams-icon.svg │ │ ├── teams │ │ │ ├── aig.svg │ │ │ ├── nasa.svg │ │ │ ├── nasdaq.svg │ │ │ ├── qualcom.svg │ │ │ └── samsung.svg │ │ ├── templates │ │ │ ├── company-goals.png │ │ │ ├── content-calendar.png │ │ │ ├── meeting-agenda.png │ │ │ ├── project-tasks.png │ │ │ ├── roadmap.png │ │ │ └── welcome.png │ │ ├── use-icon.svg │ │ └── views │ │ │ ├── boardview.png │ │ │ ├── calendarview.png │ │ │ ├── galleryview.png │ │ │ └── listview.png │ ├── js │ │ ├── main.js │ │ └── tabs.js │ ├── lottie │ │ └── intro-section.json │ ├── robots.txt │ └── video │ │ ├── accelerate1.mp4 │ │ └── comment-animation.mp4 │ └── themes │ ├── archetypes │ └── default.md │ ├── config.toml │ ├── content │ └── contribute │ │ └── _index.md │ └── layouts │ ├── 404.html │ ├── _default │ ├── list.html │ └── single.html │ ├── index.html │ └── partials │ ├── about.html │ ├── contact.html │ ├── counters.html │ ├── footer.html │ ├── head.html │ ├── hero.html │ ├── intro.html │ ├── js.html │ ├── nav.html │ ├── nav2.html │ ├── services.html │ ├── testimonials.html │ └── work.html └── win-wpf ├── .gitignore ├── AppxManifest.xml ├── Focalboard.sln ├── Focalboard ├── App.config ├── App.xaml ├── App.xaml.cs ├── Focalboard.csproj ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Utils.cs ├── Webview2Installer.cs ├── focalboard.ico └── packages.config ├── README.md ├── art ├── StoreLogo.png ├── icon150.png └── icon44.png ├── build.bat ├── package-zip.bat └── package.bat /.dockerignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | README.md 3 | 4 | node_modules 5 | .github/ 6 | mac/ 7 | win-wpf/ 8 | website/ 9 | linux/ 10 | go.work 11 | go.work.sum 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | charset = utf-8 10 | 11 | [*.go] 12 | indent_style = tab 13 | 14 | [*.{js,jsx,json,html}] 15 | indent_style = space 16 | indent_size = 4 17 | 18 | [{package.json,.eslintrc.json}] 19 | indent_size = 2 20 | 21 | [i18n/**.json] 22 | indent_size = 2 23 | 24 | [Makefile] 25 | indent_style = tab 26 | 27 | [*.scss] 28 | indent_style = space 29 | indent_size = 4 30 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | website/** linguist-documentation 2 | server/swagger/** linguist-generated 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/.github/CODEOWNERS -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement/Feature Idea 3 | about: Suggest a new capability 4 | title: 'Feature Idea: ' 5 | labels: Enhancement, Triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Summary 11 | 12 | What the new capability is. 13 | 14 | ## How important this is to me and why 15 | 16 | Importance: High/Medium/Low 17 | 18 | Use cases: 19 | 1. 20 | 2. 21 | 3. 22 | 23 | ## Additional context/similar features 24 | 25 | Any examples of good implementations of this capability. 26 | -------------------------------------------------------------------------------- /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL config" 2 | 3 | query-filters: 4 | - exclude: 5 | problem.severity: 6 | - warning 7 | - recommendation 8 | - exclude: 9 | id: go/log-injection 10 | 11 | paths-ignore: 12 | - 'server/swagger/**/*.html' 13 | - 'website/**/*.html' 14 | - '**/*_test.go' 15 | - 'webapp/cypress/**' 16 | - '**/*.test.*' 17 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | - s3 4 | 5 | variables: 6 | BUILD: "yes" 7 | IMAGE_BUILDER: $CI_REGISTRY/mattermost/ci/images/builder:go-1.19.5-node-16.15.0-1 8 | 9 | include: 10 | - project: mattermost/ci/focalboard 11 | ref: main 12 | file: private.yml 13 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | mainConfiguration: https://github.com/mattermost/mattermost-gitpod-config 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "golang.go", 4 | "dbaeumer.vscode-eslint" 5 | ] 6 | } -------------------------------------------------------------------------------- /app-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverRoot": "http://localhost:8088", 3 | "port": 8088, 4 | "dbtype": "sqlite3", 5 | "dbconfig": "./focalboard.db", 6 | "useSSL": false, 7 | "webpath": "./pack", 8 | "filespath": "./files", 9 | "telemetry": true, 10 | "localOnly": true 11 | } 12 | -------------------------------------------------------------------------------- /docker-testing/docker-compose-mysql.yml: -------------------------------------------------------------------------------- 1 | version: '2.4' 2 | services: 3 | mysql: 4 | image: "mysql/mysql-server:8.0.32" 5 | restart: always 6 | environment: 7 | MYSQL_ROOT_HOST: "%" 8 | MYSQL_ROOT_PASSWORD: mostest 9 | MYSQL_PASSWORD: mostest 10 | MYSQL_USER: mmuser 11 | healthcheck: 12 | test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] 13 | interval: 5s 14 | timeout: 10s 15 | retries: 3 16 | tmpfs: /var/lib/mysql 17 | ports: 18 | - 44446:3306 19 | 20 | start_dependencies: 21 | image: mattermost/mattermost-wait-for-dep:latest 22 | depends_on: 23 | - mysql 24 | command: mysql 25 | 26 | -------------------------------------------------------------------------------- /docker-testing/docker-compose-postgres.yml: -------------------------------------------------------------------------------- 1 | version: '2.4' 2 | services: 3 | postgres: 4 | image: "postgres:10" 5 | restart: always 6 | environment: 7 | POSTGRES_USER: mmuser 8 | POSTGRES_PASSWORD: mostest 9 | healthcheck: 10 | test: [ "CMD", "pg_isready", "-h", "localhost" ] 11 | interval: 5s 12 | timeout: 10s 13 | retries: 3 14 | tmpfs: /var/lib/postgresql/data 15 | ports: 16 | - 44447:5432 17 | 18 | start_dependencies: 19 | image: mattermost/mattermost-wait-for-dep:latest 20 | depends_on: 21 | - postgres 22 | command: postgres:5432 23 | 24 | -------------------------------------------------------------------------------- /docker/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverRoot": "http://localhost:8000", 3 | "port": 8000, 4 | "dbtype": "postgres", 5 | "dbconfig": "postgres://boardsuser:boardsuser-password@focalboard-db/boards?sslmode=disable&connect_timeout=10", 6 | "postgres_dbconfig": "dbname=boards sslmode=disable", 7 | "useSSL": false, 8 | "webpath": "./pack", 9 | "filespath": "./data/files", 10 | "telemetry": true, 11 | "prometheusaddress": ":9092", 12 | "session_expire_time": 2592000, 13 | "session_refresh_time": 18000, 14 | "localOnly": false, 15 | "enableLocalMode": true, 16 | "localModeSocketLocation": "/var/tmp/focalboard_local.socket" 17 | } 18 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | app: 4 | build: 5 | context: ../ 6 | dockerfile: docker/Dockerfile 7 | container_name: focalboard 8 | volumes: 9 | - fbdata:/opt/focalboard/data 10 | ports: 11 | - 80:8000 12 | environment: 13 | - VIRTUAL_HOST=focalboard.local 14 | - VIRTUAL_PORT=8000 15 | 16 | volumes: 17 | fbdata: -------------------------------------------------------------------------------- /docker/server_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverRoot": "http://localhost:8000", 3 | "port": 8000, 4 | "dbtype": "sqlite3", 5 | "dbconfig": "./data/focalboard.db", 6 | "postgres_dbconfig": "dbname=focalboard sslmode=disable", 7 | "useSSL": false, 8 | "webpath": "./pack", 9 | "filespath": "./data/files", 10 | "telemetry": true, 11 | "session_expire_time": 2592000, 12 | "session_refresh_time": 18000, 13 | "localOnly": false, 14 | "enableLocalMode": true, 15 | "localModeSocketLocation": "/var/tmp/focalboard_local.socket" 16 | } 17 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | title: Focalboard Developers 2 | google_analytics: UA-64458817-2 3 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /docs/manage-plugin-preferences.md: -------------------------------------------------------------------------------- 1 | # Manage plugin preferences 2 | 3 | ## Disable emojis on cards 4 | 5 | You can enable or disable random emoji icons for your board and cards by selecting the Gear icon next to your profile picture, then toggling **Random icons on or off**. 6 | -------------------------------------------------------------------------------- /experiments/webext/.gitignore: -------------------------------------------------------------------------------- 1 | .parcel-cache 2 | web-ext-artifacts 3 | -------------------------------------------------------------------------------- /experiments/webext/.parcelrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@parcel/config-webextension" 3 | } 4 | -------------------------------------------------------------------------------- /experiments/webext/icons/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/experiments/webext/icons/19.png -------------------------------------------------------------------------------- /experiments/webext/icons/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/experiments/webext/icons/38.png -------------------------------------------------------------------------------- /experiments/webext/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/experiments/webext/icons/48.png -------------------------------------------------------------------------------- /experiments/webext/icons/96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/experiments/webext/icons/96.png -------------------------------------------------------------------------------- /experiments/webext/src/utils/Board.ts: -------------------------------------------------------------------------------- 1 | interface BoardFields { 2 | isTemplate: boolean 3 | } 4 | 5 | export default interface Board { 6 | id: string 7 | title: string 8 | fields: BoardFields 9 | } 10 | -------------------------------------------------------------------------------- /experiments/webext/src/views/PopupApp.scss: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2021-present Mattermost, Inc. All Rights Reserved. */ 2 | /* See LICENSE.txt for license information. */ 3 | 4 | .PopupApp { 5 | .status { 6 | .in-progress { 7 | background-color: grey; 8 | padding: 1em; 9 | } 10 | 11 | .success { 12 | background-color: lightgreen; 13 | padding: 1em; 14 | } 15 | 16 | .error { 17 | background-color: lightpink; 18 | padding: 1em; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /experiments/webext/src/views/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /experiments/webext/src/views/options.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from "react" 5 | import ReactDOM from "react-dom" 6 | 7 | import OptionsApp from "./OptionsApp" 8 | 9 | const app = document.getElementById("app") 10 | ReactDOM.render(, app) 11 | -------------------------------------------------------------------------------- /experiments/webext/src/views/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /experiments/webext/src/views/popup.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from "react" 5 | import ReactDOM from "react-dom" 6 | 7 | import PopupApp from "./PopupApp" 8 | 9 | const app = document.getElementById("app") 10 | ReactDOM.render(, app) 11 | -------------------------------------------------------------------------------- /experiments/webext/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/README.md: -------------------------------------------------------------------------------- 1 | # Import scripts 2 | 3 | This subfolder contains scripts to import data from other systems. It is at an early stage. At present, there are examples of basic importing from the following: 4 | * Trello 5 | * Asana 6 | * Notion 7 | * Jira 8 | * Todoist 9 | * Nextcloud Deck 10 | 11 | [Contribute code](https://mattermost.github.io/focalboard/) to expand this. 12 | -------------------------------------------------------------------------------- /import/asana/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | 3 | -------------------------------------------------------------------------------- /import/asana/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/asana/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import * as crypto from 'crypto' 4 | 5 | class Utils { 6 | static createGuid(): string { 7 | function randomDigit() { 8 | if (crypto && crypto.randomBytes) { 9 | const rands = crypto.randomBytes(1) 10 | return (rands[0] % 16).toString(16) 11 | } 12 | 13 | return (Math.floor((Math.random() * 16))).toString(16) 14 | } 15 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 16 | } 17 | } 18 | 19 | export { Utils } 20 | -------------------------------------------------------------------------------- /import/jira/.gitignore: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /import/jira/importJira.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import minimist from 'minimist' 5 | import {run} from './jiraImporter' 6 | 7 | async function main() { 8 | const args: minimist.ParsedArgs = minimist(process.argv.slice(2)) 9 | 10 | const inputFile = args['i'] 11 | const outputFile = args['o'] || 'archive.boardarchive' 12 | 13 | return run(inputFile, outputFile) 14 | } 15 | 16 | main() 17 | -------------------------------------------------------------------------------- /import/jira/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/jira/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import * as crypto from 'crypto' 4 | 5 | class Utils { 6 | static createGuid(): string { 7 | function randomDigit() { 8 | if (crypto && crypto.randomBytes) { 9 | const rands = crypto.randomBytes(1) 10 | return (rands[0] % 16).toString(16) 11 | } 12 | 13 | return (Math.floor((Math.random() * 16))).toString(16) 14 | } 15 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 16 | } 17 | } 18 | 19 | export { Utils } 20 | -------------------------------------------------------------------------------- /import/nextcloud-deck/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | output.focalboard 3 | -------------------------------------------------------------------------------- /import/nextcloud-deck/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/nextcloud-deck/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import * as crypto from 'crypto' 4 | 5 | class Utils { 6 | static createGuid(): string { 7 | function randomDigit() { 8 | if (crypto && crypto.randomBytes) { 9 | const rands = crypto.randomBytes(1) 10 | return (rands[0] % 16).toString(16) 11 | } 12 | 13 | return (Math.floor((Math.random() * 16))).toString(16) 14 | } 15 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 16 | } 17 | } 18 | 19 | export { Utils } 20 | -------------------------------------------------------------------------------- /import/notion/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /import/notion/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/notion/utils.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from 'crypto' 2 | 3 | class Utils { 4 | static createGuid(): string { 5 | function randomDigit() { 6 | if (crypto && crypto.randomBytes) { 7 | const rands = crypto.randomBytes(1) 8 | return (rands[0] % 16).toString(16) 9 | } 10 | 11 | return (Math.floor((Math.random() * 16))).toString(16) 12 | } 13 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 14 | } 15 | } 16 | 17 | export { Utils } 18 | -------------------------------------------------------------------------------- /import/todoist/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /import/todoist/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/todoist/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import * as crypto from 'crypto' 4 | 5 | class Utils { 6 | static createGuid(): string { 7 | function randomDigit() { 8 | if (crypto && crypto.randomBytes) { 9 | const rands = crypto.randomBytes(1) 10 | return (rands[0] % 16).toString(16) 11 | } 12 | 13 | return (Math.floor((Math.random() * 16))).toString(16) 14 | } 15 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 16 | } 17 | } 18 | 19 | export { Utils } 20 | -------------------------------------------------------------------------------- /import/trello/.gitignore: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /import/trello/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "es2019", 5 | "module": "commonjs", 6 | "esModuleInterop": true, 7 | "noImplicitAny": true, 8 | "strict": true, 9 | "strictNullChecks": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "resolveJsonModule": true, 14 | "incremental": false, 15 | "outDir": "./dist", 16 | "moduleResolution": "node" 17 | }, 18 | "include": [ 19 | "." 20 | ], 21 | "exclude": [ 22 | ".git", 23 | "**/node_modules/*", 24 | "dist", 25 | "pack" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /import/trello/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import * as crypto from 'crypto' 4 | 5 | class Utils { 6 | static createGuid(): string { 7 | function randomDigit() { 8 | if (crypto && crypto.randomBytes) { 9 | const rands = crypto.randomBytes(1) 10 | return (rands[0] % 16).toString(16) 11 | } 12 | 13 | return (Math.floor((Math.random() * 16))).toString(16) 14 | } 15 | return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit) 16 | } 17 | } 18 | 19 | export { Utils } 20 | -------------------------------------------------------------------------------- /linux/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run 2 | 3 | run: 4 | go run -tags "json1 sqlite3" ./main.go 5 | 6 | build: 7 | mkdir -p bin 8 | go build -tags "json1 sqlite3" -o bin/focalboard-app 9 | -------------------------------------------------------------------------------- /linux/config.json: -------------------------------------------------------------------------------- 1 | ../config.json -------------------------------------------------------------------------------- /linux/pack: -------------------------------------------------------------------------------- 1 | ../webapp/pack -------------------------------------------------------------------------------- /linux/webapp: -------------------------------------------------------------------------------- 1 | ../webapp -------------------------------------------------------------------------------- /mac/Focalboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mac/Focalboard.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /mac/Focalboard.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mac/Focalboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /mac/Focalboard/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /mac/Focalboard/Assets.xcassets/AppIcon.appiconset/focalboard-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/mac/Focalboard/Assets.xcassets/AppIcon.appiconset/focalboard-1024.png -------------------------------------------------------------------------------- /mac/Focalboard/Assets.xcassets/AppIcon.appiconset/focalboard-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/mac/Focalboard/Assets.xcassets/AppIcon.appiconset/focalboard-512.png -------------------------------------------------------------------------------- /mac/Focalboard/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /mac/Focalboard/AutoSaveWindowController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import Cocoa 5 | 6 | class AutoSaveWindowController: NSWindowController { 7 | 8 | override func windowDidLoad() { 9 | super.windowDidLoad() 10 | 11 | // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 12 | self.windowFrameAutosaveName = NSWindow.FrameAutosaveName("AutoSaveWindow") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /mac/Focalboard/Focalboard.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-write 8 | 9 | com.apple.security.network.client 10 | 11 | com.apple.security.network.server 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /mac/Focalboard/Inherit.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.inherit 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /mac/export.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | compileBitcode 6 | 7 | method 8 | development 9 | signingStyle 10 | automatic 11 | stripSwiftSymbols 12 | 13 | thinning 14 | <none> 15 | 16 | 17 | -------------------------------------------------------------------------------- /modd-servertest.conf: -------------------------------------------------------------------------------- 1 | **/*.go { 2 | prep: cd server && go test -tags "$FOCALBOARD_BUILD_TAGS" -race -v ./... 3 | } 4 | -------------------------------------------------------------------------------- /modd.conf: -------------------------------------------------------------------------------- 1 | **/*.go !**/*_test.go { 2 | prep: cd server && go build -tags "$FOCALBOARD_BUILD_TAGS" -o ../bin/focalboard-server ./main 3 | daemon +sigterm: ./bin/focalboard-server $FOCALBOARDSERVER_ARGS 4 | } 5 | 6 | { 7 | daemon: cd webapp && npm run watchdev 8 | } 9 | -------------------------------------------------------------------------------- /noticegen/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: "Mattermost Focalboard" 4 | copyright: "©2015-present Mattermost,Inc. All Rights Reserved. See LICENSE for license information." 5 | description: "This document includes a list of open source components used in Mattermost Focalboard, including those that have been modified." 6 | search: 7 | - "server/go.mod" 8 | - "linux/go.mod" 9 | dependencies: [] 10 | devDependencies: [] 11 | 12 | ... 13 | -------------------------------------------------------------------------------- /server-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverRoot": "http://localhost:8000", 3 | "port": 8000, 4 | "dbtype": "sqlite3", 5 | "dbconfig": "./focalboard.db", 6 | "postgres_dbconfig": "dbname=focalboard sslmode=disable", 7 | "useSSL": false, 8 | "webpath": "./pack", 9 | "filespath": "./files", 10 | "telemetry": true, 11 | "prometheusaddress": ":9092", 12 | "session_expire_time": 2592000, 13 | "session_refresh_time": 18000, 14 | "localOnly": false, 15 | "enableLocalMode": true, 16 | "localModeSocketLocation": "/var/tmp/focalboard_local.socket" 17 | } 18 | -------------------------------------------------------------------------------- /server/admin-scripts/reset-password.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $# < 2 ]] ; then 4 | echo 'reset-password.sh ' 5 | exit 1 6 | fi 7 | 8 | curl --unix-socket /var/tmp/focalboard_local.socket http://localhost/api/v2/admin/users/$1/password -X POST -H 'Content-Type: application/json' -d '{ "password": "'$2'" }' 9 | -------------------------------------------------------------------------------- /server/app/app_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/mattermost/focalboard/server/services/config" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestSetConfig(t *testing.T) { 11 | th, tearDown := SetupTestHelper(t) 12 | defer tearDown() 13 | 14 | t.Run("Test Update Config", func(t *testing.T) { 15 | require.False(t, th.App.config.EnablePublicSharedBoards) 16 | newConfiguration := config.Configuration{} 17 | newConfiguration.EnablePublicSharedBoards = true 18 | th.App.SetConfig(&newConfiguration) 19 | 20 | require.True(t, th.App.config.EnablePublicSharedBoards) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /server/app/clientConfig.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/mattermost/focalboard/server/model" 5 | ) 6 | 7 | func (a *App) GetClientConfig() *model.ClientConfig { 8 | return &model.ClientConfig{ 9 | Telemetry: a.config.Telemetry, 10 | TelemetryID: a.config.TelemetryID, 11 | EnablePublicSharedBoards: a.config.EnablePublicSharedBoards, 12 | TeammateNameDisplay: a.config.TeammateNameDisplay, 13 | FeatureFlags: a.config.FeatureFlags, 14 | MaxFileSize: a.config.MaxFileSize, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /server/app/compliance.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import "github.com/mattermost/focalboard/server/model" 4 | 5 | func (a *App) GetBoardsForCompliance(opts model.QueryBoardsForComplianceOptions) ([]*model.Board, bool, error) { 6 | return a.store.GetBoardsForCompliance(opts) 7 | } 8 | 9 | func (a *App) GetBoardsComplianceHistory(opts model.QueryBoardsComplianceHistoryOptions) ([]*model.BoardHistory, bool, error) { 10 | return a.store.GetBoardsComplianceHistory(opts) 11 | } 12 | 13 | func (a *App) GetBlocksComplianceHistory(opts model.QueryBlocksComplianceHistoryOptions) ([]*model.BlockHistory, bool, error) { 14 | return a.store.GetBlocksComplianceHistory(opts) 15 | } 16 | -------------------------------------------------------------------------------- /server/app/permissions.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | mm_model "github.com/mattermost/mattermost/server/public/model" 5 | ) 6 | 7 | func (a *App) HasPermissionToBoard(userID, boardID string, permission *mm_model.Permission) bool { 8 | return a.permissions.HasPermissionToBoard(userID, boardID, permission) 9 | } 10 | -------------------------------------------------------------------------------- /server/app/sharing.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/mattermost/focalboard/server/model" 5 | ) 6 | 7 | func (a *App) GetSharing(boardID string) (*model.Sharing, error) { 8 | sharing, err := a.store.GetSharing(boardID) 9 | if err != nil { 10 | return nil, err 11 | } 12 | return sharing, nil 13 | } 14 | 15 | func (a *App) UpsertSharing(sharing model.Sharing) error { 16 | return a.store.UpsertSharing(sharing) 17 | } 18 | -------------------------------------------------------------------------------- /server/app/statistics.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | package app 5 | 6 | func (a *App) GetUsedCardsCount() (int, error) { 7 | return a.store.GetUsedCardsCount() 8 | } 9 | -------------------------------------------------------------------------------- /server/app/templates.boardarchive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/app/templates.boardarchive -------------------------------------------------------------------------------- /server/assets/assets.go: -------------------------------------------------------------------------------- 1 | package assets 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | // DefaultTemplatesArchive is an embedded archive file containing the default 8 | // templates to be imported to team 0. 9 | // This archive is generated with `make templates-archive` 10 | // 11 | //go:embed templates.boardarchive 12 | var DefaultTemplatesArchive []byte 13 | -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/bbn1888mprfrm5fjw9f1je9x3xo/76fwrj36hptg6dywka4k5mt3sph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/bbn1888mprfrm5fjw9f1je9x3xo/76fwrj36hptg6dywka4k5mt3sph.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/bgi1yqiis8t8xdqxgnet8ebutky/7b9xk9boj3fbqfm3umeaaizp8qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/bgi1yqiis8t8xdqxgnet8ebutky/7b9xk9boj3fbqfm3umeaaizp8qr.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/bgi1yqiis8t8xdqxgnet8ebutky/7tmfu5iqju3n1mdfwi5gru89qmw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/bgi1yqiis8t8xdqxgnet8ebutky/7tmfu5iqju3n1mdfwi5gru89qmw.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/brs9cdimfw7fodyi7erqt747rhc/7y5kr8x8ybpnwdykjfuz57rggrh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/brs9cdimfw7fodyi7erqt747rhc/7y5kr8x8ybpnwdykjfuz57rggrh.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/bui5izho7dtn77xg3thkiqprc9r/77pe9r4ckbin438ph3f18bpatua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/bui5izho7dtn77xg3thkiqprc9r/77pe9r4ckbin438ph3f18bpatua.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/bui5izho7dtn77xg3thkiqprc9r/7pbp4qg415pbstc6enzeicnu3qh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/bui5izho7dtn77xg3thkiqprc9r/7pbp4qg415pbstc6enzeicnu3qh.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/74nt9eqzea3ydjjpgjtsxcjgrxc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/74nt9eqzea3ydjjpgjtsxcjgrxc.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/74uia99m9btr8peydw7oexn37tw.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/74uia99m9btr8peydw7oexn37tw.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/78jws5m1myf8pufewzkaa6i11sc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/78jws5m1myf8pufewzkaa6i11sc.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7d6hrtig3zt8f9cnbo1um5oxx3y.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7d6hrtig3zt8f9cnbo1um5oxx3y.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7dybb6t8fj3nrdft7nerhuf784y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7dybb6t8fj3nrdft7nerhuf784y.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7ek6wbpp19jfoujs1goh6kttbby.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7ek6wbpp19jfoujs1goh6kttbby.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7iw4rxx7jj7bypmdotd9z469cyh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7iw4rxx7jj7bypmdotd9z469cyh.png -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7knxbyuiedtdafcgmropgkrtybr.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates-boardarchive/buixxjic3xjfkieees4iafdrznc/7knxbyuiedtdafcgmropgkrtybr.gif -------------------------------------------------------------------------------- /server/assets/templates-boardarchive/version.json: -------------------------------------------------------------------------------- 1 | {"version":2,"date":1643788318636} 2 | -------------------------------------------------------------------------------- /server/assets/templates.boardarchive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/assets/templates.boardarchive -------------------------------------------------------------------------------- /server/go.tools.mod: -------------------------------------------------------------------------------- 1 | module github.com/mattermost/focalboard/server 2 | 3 | go 1.19 4 | 5 | require github.com/golang/mock v1.6.0 6 | 7 | require ( 8 | github.com/jteeuwen/go-bindata v3.0.7+incompatible // indirect 9 | golang.org/x/mod v0.4.2 // indirect 10 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect 11 | golang.org/x/tools v0.1.1 // indirect 12 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /server/model/board_statistics.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | package model 4 | 5 | // BoardsStatistics is the representation of the statistics for the Boards server 6 | // swagger:model 7 | type BoardsStatistics struct { 8 | // The maximum number of cards on the server 9 | // required: true 10 | Boards int `json:"board_count"` 11 | 12 | // The maximum number of cards on the server 13 | // required: true 14 | Cards int `json:"card_count"` 15 | } 16 | -------------------------------------------------------------------------------- /server/model/database.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | const ( 4 | SqliteDBType = "sqlite3" 5 | PostgresDBType = "postgres" 6 | MysqlDBType = "mysql" 7 | ) 8 | -------------------------------------------------------------------------------- /server/model/errorResponse.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // ErrorResponse is an error response 4 | // swagger:model 5 | type ErrorResponse struct { 6 | // The error message 7 | // required: false 8 | Error string `json:"error"` 9 | 10 | // The error code 11 | // required: false 12 | ErrorCode int `json:"errorCode"` 13 | } 14 | -------------------------------------------------------------------------------- /server/model/log_level.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import "github.com/mattermost/logr/v2" 4 | 5 | var LvlFBTelemetry = logr.Level{ 6 | ID: 9000, 7 | Name: "telemetry", 8 | } 9 | -------------------------------------------------------------------------------- /server/server/initHandlers.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | func (s *Server) initHandlers() { 4 | cfg := s.config 5 | s.api.MattermostAuth = cfg.AuthMode == MattermostAuthMod 6 | } 7 | -------------------------------------------------------------------------------- /server/services/auth/email.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "regexp" 4 | 5 | var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 6 | 7 | // IsEmailValid checks if the email provided passes the required structure and length. 8 | func IsEmailValid(e string) bool { 9 | if len(e) < 3 || len(e) > 254 { 10 | return false 11 | } 12 | return emailRegex.MatchString(e) 13 | } 14 | -------------------------------------------------------------------------------- /server/services/notify/notifymentions/app_api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | package notifymentions 4 | 5 | import "github.com/mattermost/focalboard/server/model" 6 | 7 | type AppAPI interface { 8 | GetMemberForBoard(boardID, userID string) (*model.BoardMember, error) 9 | AddMemberToBoard(member *model.BoardMember) (*model.BoardMember, error) 10 | } 11 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000001_init.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000002_system_settings_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000002_system_settings_table.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}system_settings ( 2 | id VARCHAR(100), 3 | value TEXT, 4 | PRIMARY KEY (id) 5 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 6 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000003_blocks_rootid.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000003_blocks_rootid.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "blocks" "root_id" "varchar(36)" ""}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000004_auth_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000005_blocks_modifiedby.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000005_blocks_modifiedby.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "blocks" "modified_by" "varchar(36)" ""}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000006_sharing_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000006_sharing_table.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}sharing ( 2 | id VARCHAR(36), 3 | enabled BOOLEAN, 4 | token VARCHAR(100), 5 | modified_by VARCHAR(36), 6 | update_at BIGINT, 7 | PRIMARY KEY (id) 8 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 9 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000007_workspaces_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000007_workspaces_table.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}workspaces ( 2 | id VARCHAR(36), 3 | signup_token VARCHAR(100) NOT NULL, 4 | settings {{if .postgres}}JSON{{else}}TEXT{{end}}, 5 | modified_by VARCHAR(36), 6 | update_at BIGINT, 7 | PRIMARY KEY (id) 8 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 9 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000008_teams.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000008_teams.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "blocks" "workspace_id" "varchar(36)" ""}} 3 | 4 | {{ addColumnIfNeeded "sharing" "workspace_id" "varchar(36)" ""}} 5 | 6 | {{ addColumnIfNeeded "sessions" "auth_service" "varchar(20)" ""}} 7 | 8 | UPDATE {{.prefix}}blocks SET workspace_id = '0' WHERE workspace_id = '' OR workspace_id IS NULL; 9 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000009_blocks_history.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000010_blocks_created_by.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000010_blocks_created_by.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint) */ -}} 2 | {{ addColumnIfNeeded "blocks" "created_by" "varchar(36)" ""}} 3 | {{ addColumnIfNeeded "blocks_history" "created_by" "varchar(36)" ""}} 4 | 5 | UPDATE {{.prefix}}blocks SET created_by = 6 | COALESCE(NULLIF((select modified_by from {{.prefix}}blocks_history where {{.prefix}}blocks_history.id = {{.prefix}}blocks.id ORDER BY {{.prefix}}blocks_history.insert_at ASC limit 1), ''), 'system') 7 | WHERE created_by IS NULL; 8 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000011_match_collation.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000011_match_collation.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* All tables have collation fixed via code at startup so this migration is no longer needed. */ -}} 2 | {{- /* See https://github.com/mattermost/focalboard/pull/4002 */ -}} 3 | 4 | SELECT 1; 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000012_match_column_collation.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000013_millisecond_timestamps.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000014_add_not_null_constraint.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000014_add_not_null_constraint.up.sql: -------------------------------------------------------------------------------- 1 | UPDATE {{.prefix}}blocks SET created_by = 'system' where created_by IS NULL; 2 | UPDATE {{.prefix}}blocks SET modified_by = 'system' where modified_by IS NULL; 3 | 4 | {{if .mysql}} 5 | ALTER TABLE {{.prefix}}blocks MODIFY created_by varchar(36) NOT NULL; 6 | ALTER TABLE {{.prefix}}blocks MODIFY modified_by varchar(36) NOT NULL; 7 | {{end}} 8 | 9 | {{if .postgres}} 10 | ALTER TABLE {{.prefix}}blocks ALTER COLUMN created_by set NOT NULL; 11 | ALTER TABLE {{.prefix}}blocks ALTER COLUMN modified_by set NOT NULL; 12 | {{end}} 13 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000015_blocks_history_no_nulls.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000016_subscriptions_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000017_add_file_info.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000017_add_file_info.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}file_info ( 2 | id varchar(26) NOT NULL, 3 | create_at BIGINT NOT NULL, 4 | delete_at BIGINT, 5 | name TEXT NOT NULL, 6 | extension VARCHAR(50) NOT NULL, 7 | size BIGINT NOT NULL, 8 | archived BOOLEAN 9 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 10 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000018_add_teams_and_boards.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000019_populate_categories.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000019_populate_categories.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}categories ( 2 | id varchar(36) NOT NULL, 3 | name varchar(100) NOT NULL, 4 | user_id varchar(36) NOT NULL, 5 | team_id varchar(36) NOT NULL, 6 | channel_id varchar(36), 7 | create_at BIGINT, 8 | update_at BIGINT, 9 | delete_at BIGINT, 10 | PRIMARY KEY (id) 11 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 12 | 13 | {{- /* createIndexIfNeeded tableName columns */ -}} 14 | {{ createIndexIfNeeded "categories" "user_id, team_id" }} 15 | 16 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000020_populate_category_blocks.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000020_populate_category_blocks.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}category_boards ( 2 | id varchar(36) NOT NULL, 3 | user_id varchar(36) NOT NULL, 4 | category_id varchar(36) NOT NULL, 5 | board_id VARCHAR(36) NOT NULL, 6 | create_at BIGINT, 7 | update_at BIGINT, 8 | delete_at BIGINT, 9 | PRIMARY KEY (id) 10 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 11 | 12 | {{- /* createIndexIfNeeded tableName columns */ -}} 13 | {{ createIndexIfNeeded "category_boards" "category_id" }} 14 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000021_create_boards_members_history.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000022_create_default_board_role.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000022_create_default_board_role.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "boards" "minimum_role" "varchar(36)" "NOT NULL DEFAULT ''"}} 3 | {{ addColumnIfNeeded "boards_history" "minimum_role" "varchar(36)" "NOT NULL DEFAULT ''"}} 4 | 5 | UPDATE {{.prefix}}boards SET minimum_role = 'editor' WHERE minimum_role IS NULL OR minimum_role=''; 6 | UPDATE {{.prefix}}boards_history SET minimum_role = 'editor' WHERE minimum_role IS NULL OR minimum_role=''; 7 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000023_persist_category_collapsed_state.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000023_persist_category_collapsed_state.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "categories" "collapsed" "boolean" "default false"}} 3 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000024_mark_existsing_categories_collapsed.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000024_mark_existsing_categories_collapsed.up.sql: -------------------------------------------------------------------------------- 1 | UPDATE {{.prefix}}categories SET collapsed = true; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000025_indexes_update.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000026_create_preferences_table.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000026_create_preferences_table.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS {{.prefix}}preferences 2 | ( 3 | userid VARCHAR(36) NOT NULL, 4 | category VARCHAR(32) NOT NULL, 5 | name VARCHAR(32) NOT NULL, 6 | value TEXT NULL, 7 | PRIMARY KEY (userid, category, name) 8 | ) {{if .mysql}}DEFAULT CHARACTER SET utf8mb4{{end}}; 9 | 10 | {{- /* createIndexIfNeeded tableName columns */ -}} 11 | {{ createIndexIfNeeded "preferences" "category" }} 12 | {{ createIndexIfNeeded "preferences" "name" }} 13 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000027_migrate_user_props_to_preferences.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000028_remove_template_channel_link.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000028_remove_template_channel_link.up.sql: -------------------------------------------------------------------------------- 1 | UPDATE {{.prefix}}boards SET channel_id = '' WHERE is_template; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000029_add_category_type_field.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000029_add_category_type_field.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "categories" "type" "varchar(64)" ""}} 3 | 4 | UPDATE {{.prefix}}categories SET type = 'custom' WHERE type IS NULL; 5 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000030_add_category_sort_order.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000030_add_category_sort_order.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "categories" "sort_order" "BIGINT" ""}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.up.sql: -------------------------------------------------------------------------------- 1 | {{- /* addColumnIfNeeded tableName columnName datatype constraint */ -}} 2 | {{ addColumnIfNeeded "category_boards" "sort_order" "BIGINT" ""}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000033_remove_deleted_category_boards.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000033_remove_deleted_category_boards.up.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM {{.prefix}}category_boards WHERE delete_at > 0; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000034_category_boards_remove_unused_delete_at_column.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000034_category_boards_remove_unused_delete_at_column.up.sql: -------------------------------------------------------------------------------- 1 | {{ if or .postgres .mysql }} 2 | {{ dropColumnIfNeeded "category_boards" "delete_at" }} 3 | {{end}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000035_add_hidden_board_column.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000035_add_hidden_board_column.up.sql: -------------------------------------------------------------------------------- 1 | {{ addColumnIfNeeded "category_boards" "hidden" "boolean" "" }} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000036_category_board_add_unique_constraint.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000037_hidden_boards_from_preferences.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000038_delete_hiddenBoardIDs_from_preferences.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000038_delete_hiddenBoardIDs_from_preferences.up.sql: -------------------------------------------------------------------------------- 1 | {{if .plugin}} 2 | DELETE FROM Preferences WHERE category = 'focalboard' AND name = 'hiddenBoardIDs'; 3 | {{else}} 4 | DELETE FROM {{.prefix}}preferences WHERE category = 'focalboard' AND name = 'hiddenBoardIDs'; 5 | {{end}} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000039_add_path_to_file_info.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000039_add_path_to_file_info.up.sql: -------------------------------------------------------------------------------- 1 | {{ addColumnIfNeeded "file_info" "path" "varchar(512)" "" }} -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.down.sql: -------------------------------------------------------------------------------- 1 | SELECT 1; 2 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrations/000040_fix_fileinfo_soft_deletes.up.sql: -------------------------------------------------------------------------------- 1 | {{if .plugin}} 2 | UPDATE FileInfo 3 | SET DeleteAt = 0 4 | WHERE CreatorId = 'boards' 5 | AND DeleteAt != 0; 6 | {{else}} 7 | SELECT 1; 8 | {{end}} 9 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test27MigrateUserPropsToPreferences.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO focalboard_users 2 | (id, username, props) 3 | VALUES 4 | ('user-id', 'johndoe', '{"focalboard_welcomePageViewed": true, "hiddenBoardIDs": ["board1", "board2"], "focalboard_tourCategory": "onboarding", "focalboard_onboardingTourStep": 1, "focalboard_onboardingTourStarted": false, "focalboard_version72MessageCanceled": true, "focalboard_lastWelcomeVersion": 7}'); 5 | 6 | INSERT INTO focalboard_preferences 7 | (UserId, Category, Name, Value) 8 | VALUES 9 | ('user-id', 'focalboard', 'onboardingTourStarted', true); 10 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test28RemoveTemplateChannelLink.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO focalboard_boards 2 | (id, title, type, is_template, channel_id, team_id) 3 | VALUES 4 | ('board-id', 'Board', 'O', false, 'linked-channel', 'team-id'), 5 | ('template-id', 'Template', 'O', true, 'linked-channel', 'team-id'); 6 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test33_with_no_deleted_data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO focalboard_category_boards 2 | (id, user_id, category_id, board_id, create_at, update_at, delete_at, sort_order) 3 | values 4 | ('id-1', 'user_id-1', 'category-id-1', 'board-id-1', 1672988834402, 1672988834402, 0, 0), 5 | ('id-2', 'user_id-1', 'category-id-2', 'board-id-1', 1672988834402, 1672988834402, 0, 0), 6 | ('id-3', 'user_id-2', 'category-id-3', 'board-id-2', 1672988834402, 1672988834402, 0, 0), 7 | ('id-4', 'user_id-2', 'category-id-3', 'board-id-4', 1672988834402, 1672988834402, 0, 0), 8 | ('id-5', 'user_id-3', 'category-id-4', 'board-id-3', 1672988834402, 1672988834402, 0, 0); 9 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test34_drop_delete_at_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE focalboard_category_boards DROP COLUMN delete_at; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test35_add_hidden_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE focalboard_category_boards ADD COLUMN hidden boolean; -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test36_add_unique_constraint.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/server/services/store/sqlstore/migrationstests/fixtures/test36_add_unique_constraint.sql -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test38_add_plugin_preferences.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO Preferences VALUES 2 | ('user-id-1', 'focalboard', 'hiddenBoardIDs', '["board-id-1"]'), 3 | ('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'), 4 | ('user-id-3', 'lorem', 'lorem', ''), 5 | ('user-id-4', 'ipsum', 'ipsum', ''); -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test38_add_standalone_preferences.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO focalboard_preferences VALUES 2 | ('user-id-1', 'focalboard', 'hiddenBoardIDs', '["board-id-1"]'), 3 | ('user-id-2', 'focalboard', 'hiddenBoardIDs', '["board-id-3", "board-id-4"]'), 4 | ('user-id-2', 'lorem', 'lorem', ''), 5 | ('user-id-2', 'ipsum', 'ipsum', ''); -------------------------------------------------------------------------------- /server/services/store/sqlstore/migrationstests/fixtures/test40FixFileinfoSoftDeletes.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO FileInfo 2 | (Id, CreatorId, CreateAt, UpdateAt, DeleteAt) 3 | VALUES 4 | ('fileinfo-1', 'user-id', 1, 1, 1000), 5 | ('fileinfo-2', 'user-id', 1, 1, 1000), 6 | ('fileinfo-3', 'user-id', 1, 1, 0), 7 | ('fileinfo-4', 'boards', 1, 1, 2000), 8 | ('fileinfo-5', 'boards', 1, 1, 2000), 9 | ('fileinfo-6', 'boards', 1, 1, 0); 10 | -------------------------------------------------------------------------------- /server/services/store/sqlstore/sqlite.go: -------------------------------------------------------------------------------- 1 | //go:build sqlite3 2 | 3 | package sqlstore 4 | 5 | import _ "github.com/mattn/go-sqlite3" // sqlite driver 6 | -------------------------------------------------------------------------------- /server/swagger/docs/html/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 6.2.1 -------------------------------------------------------------------------------- /server/utils/debug.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | ) 7 | 8 | // IsRunningUnitTests returns true if this instance of FocalBoard is running unit or integration tests. 9 | func IsRunningUnitTests() bool { 10 | testing := os.Getenv("FOCALBOARD_UNIT_TESTING") 11 | if testing == "" { 12 | return false 13 | } 14 | 15 | switch strings.ToLower(testing) { 16 | case "1", "t", "y", "true", "yes": 17 | return true 18 | } 19 | return false 20 | } 21 | -------------------------------------------------------------------------------- /server/utils/links.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | package utils 5 | 6 | import "fmt" 7 | 8 | // MakeCardLink creates fully qualified card links based on card id and parents. 9 | func MakeCardLink(serverRoot string, teamID string, boardID string, cardID string) string { 10 | return fmt.Sprintf("%s/team/%s/%s/0/%s", serverRoot, teamID, boardID, cardID) 11 | } 12 | 13 | func MakeBoardLink(serverRoot string, teamID string, board string) string { 14 | return fmt.Sprintf("%s/team/%s/%s", serverRoot, teamID, board) 15 | } 16 | -------------------------------------------------------------------------------- /server/utils/testUtils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | var Anything = mock.MatchedBy(func(interface{}) bool { return true }) 6 | -------------------------------------------------------------------------------- /webapp/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /webapp/.nvmrc: -------------------------------------------------------------------------------- 1 | 20.11 2 | -------------------------------------------------------------------------------- /webapp/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore all js/ts files: 2 | *.ts 3 | *.tsx 4 | *.js -------------------------------------------------------------------------------- /webapp/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4 3 | } 4 | -------------------------------------------------------------------------------- /webapp/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-sass-guidelines", 3 | "rules": { 4 | "indentation": 4, 5 | "selector-class-pattern": "[a-zA-Z_-]+", 6 | "max-nesting-depth": 4, 7 | "selector-max-compound-selectors": 6, 8 | "selector-max-id": 1, 9 | "selector-no-qualifying-type": null, 10 | "order/properties-alphabetical-order": null, 11 | "declaration-block-no-duplicate-properties": true, 12 | "property-disallowed-list": ["z-index"] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | module.exports = 'test-file-stub'; 4 | -------------------------------------------------------------------------------- /webapp/__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | module.exports = {}; 4 | -------------------------------------------------------------------------------- /webapp/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "chromeWebSecurity": false, 3 | "baseUrl": "http://localhost:8088", 4 | "testFiles": [ 5 | "**/login*.ts", 6 | "**/create*.ts", 7 | "**/manage*.ts", 8 | "**/group*.ts", 9 | "**/card*.ts" 10 | ], 11 | "env": { 12 | "username": "test-user", 13 | "password": "test-password", 14 | "email": "test@mail.com" 15 | }, 16 | "video": false, 17 | "viewportWidth": 1600, 18 | "viewportHeight": 1200 19 | } 20 | -------------------------------------------------------------------------------- /webapp/cypress/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverRoot": "http://localhost:8088", 3 | "port": 8088, 4 | "dbtype": "sqlite3", 5 | "dbconfig": "file::memory:?cache=shared&_busy_timeout=5000", 6 | "useSSL": false, 7 | "webpath": "../pack", 8 | "filespath": "../../files", 9 | "telemetry": false, 10 | "webhook_update": [], 11 | "session_expire_time": 2592000, 12 | "session_refresh_time": 18000 13 | } 14 | -------------------------------------------------------------------------------- /webapp/cypress/support/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import '@testing-library/cypress/add-commands' 5 | 6 | import 'cypress-real-events/support' 7 | 8 | import './api_commands' 9 | import './ui_commands' 10 | 11 | import 'cypress-failed-log' 12 | -------------------------------------------------------------------------------- /webapp/cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "types": [ 6 | "cypress", 7 | "cypress-real-events", 8 | "@testing-library/cypress" 9 | ] 10 | }, 11 | "include": [ 12 | "**/*.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /webapp/html-templates/deveditor.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /webapp/html-templates/page.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /webapp/i18n/ars.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /webapp/i18n/kab.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /webapp/i18n/lt.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /webapp/i18n/sl.json: -------------------------------------------------------------------------------- 1 | { 2 | "BoardComponent.add-a-group": "+ Dodaj skupino", 3 | "BoardComponent.delete": "Izbriši", 4 | "BoardComponent.hidden-columns": "Skriti stolpci", 5 | "BoardComponent.hide": "Skrij", 6 | "BoardComponent.new": "+ Novo", 7 | "BoardComponent.no-property": "Ni {property}", 8 | "BoardComponent.no-property-title": "Elementi s prazno lastnostjo {property} bodo šli sem. Tega stolpca ni mogoče odstraniti.", 9 | "BoardComponent.show": "Pokaži", 10 | "BoardPage.newVersion": "Na voljo je nova različica Boards, kliknite tukaj za ponovno nalaganje.", 11 | "BoardPage.syncFailed": "Plošča se lahko izbriše ali dostop prekliče." 12 | } 13 | -------------------------------------------------------------------------------- /webapp/src/blockIcons.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {randomEmojiList} from './emojiList' 4 | 5 | class BlockIcons { 6 | static readonly shared = new BlockIcons() 7 | 8 | randomIcon(): string { 9 | const index = Math.floor(Math.random() * randomEmojiList.length) 10 | const icon = randomEmojiList[index] 11 | return icon 12 | } 13 | } 14 | 15 | export {BlockIcons} 16 | -------------------------------------------------------------------------------- /webapp/src/blocks/checkboxBlock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {ContentBlock} from './contentBlock' 4 | import {Block, createBlock} from './block' 5 | 6 | type CheckboxBlock = ContentBlock & { 7 | type: 'checkbox' 8 | } 9 | 10 | function createCheckboxBlock(block?: Block): CheckboxBlock { 11 | return { 12 | ...createBlock(block), 13 | type: 'checkbox', 14 | } 15 | } 16 | 17 | export {CheckboxBlock, createCheckboxBlock} 18 | -------------------------------------------------------------------------------- /webapp/src/blocks/commentBlock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {Block, createBlock} from './block' 4 | 5 | type CommentBlock = Block & { 6 | type: 'comment' 7 | } 8 | 9 | function createCommentBlock(block?: Block): CommentBlock { 10 | return { 11 | ...createBlock(block), 12 | type: 'comment', 13 | } 14 | } 15 | 16 | export {CommentBlock, createCommentBlock} 17 | -------------------------------------------------------------------------------- /webapp/src/blocks/contentBlock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {Block, createBlock} from './block' 4 | 5 | type IContentBlockWithCords = { 6 | block: Block 7 | cords: {x: number, y?: number, z?: number} 8 | } 9 | 10 | type ContentBlock = Block 11 | 12 | const createContentBlock = createBlock 13 | 14 | export {ContentBlock, IContentBlockWithCords, createContentBlock} 15 | -------------------------------------------------------------------------------- /webapp/src/blocks/dividerBlock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {Block, createBlock} from './block' 4 | import {ContentBlock} from './contentBlock' 5 | 6 | type DividerBlock = ContentBlock & { 7 | type: 'divider' 8 | } 9 | 10 | function createDividerBlock(block?: Block): DividerBlock { 11 | return { 12 | ...createBlock(block), 13 | type: 'divider', 14 | } 15 | } 16 | 17 | export {DividerBlock, createDividerBlock} 18 | -------------------------------------------------------------------------------- /webapp/src/blocks/h1Block.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {ContentBlock} from './contentBlock' 4 | import {Block, createBlock} from './block' 5 | 6 | type H1Block = ContentBlock & { 7 | type: 'h1' 8 | } 9 | 10 | function createH1Block(block?: Block): H1Block { 11 | return { 12 | ...createBlock(block), 13 | type: 'h1', 14 | } 15 | } 16 | 17 | export {H1Block, createH1Block} 18 | 19 | -------------------------------------------------------------------------------- /webapp/src/blocks/h2Block.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {ContentBlock} from './contentBlock' 4 | import {Block, createBlock} from './block' 5 | 6 | type H2Block = ContentBlock & { 7 | type: 'h2' 8 | } 9 | 10 | function createH2Block(block?: Block): H2Block { 11 | return { 12 | ...createBlock(block), 13 | type: 'h2', 14 | } 15 | } 16 | 17 | export {H2Block, createH2Block} 18 | 19 | -------------------------------------------------------------------------------- /webapp/src/blocks/h3Block.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {ContentBlock} from './contentBlock' 4 | import {Block, createBlock} from './block' 5 | 6 | type H3Block = ContentBlock & { 7 | type: 'h3' 8 | } 9 | 10 | function createH3Block(block?: Block): H3Block { 11 | return { 12 | ...createBlock(block), 13 | type: 'h3', 14 | } 15 | } 16 | 17 | export {H3Block, createH3Block} 18 | 19 | -------------------------------------------------------------------------------- /webapp/src/blocks/sharing.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | interface ISharing { 5 | id: string 6 | enabled: boolean 7 | token: string 8 | modifiedBy?: string 9 | updateAt?: number 10 | } 11 | 12 | export {ISharing} 13 | -------------------------------------------------------------------------------- /webapp/src/blocks/team.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | interface ITeam { 4 | readonly id: string 5 | readonly title: string 6 | readonly signupToken: string 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | readonly settings: Readonly> 9 | readonly modifiedBy?: string 10 | readonly updateAt?: number 11 | } 12 | 13 | export {ITeam} 14 | -------------------------------------------------------------------------------- /webapp/src/blocks/textBlock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {ContentBlock} from './contentBlock' 4 | import {Block, createBlock} from './block' 5 | 6 | type TextBlock = ContentBlock & { 7 | type: 'text' 8 | } 9 | 10 | function createTextBlock(block?: Block): TextBlock { 11 | return { 12 | ...createBlock(block), 13 | type: 'text', 14 | } 15 | } 16 | 17 | export {TextBlock, createTextBlock} 18 | -------------------------------------------------------------------------------- /webapp/src/blocks/workspace.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | interface IWorkspace { 4 | readonly id: string 5 | readonly title: string 6 | readonly signupToken: string 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | readonly settings: Readonly> 9 | readonly modifiedBy?: string 10 | readonly updateAt?: number 11 | } 12 | 13 | export {IWorkspace} 14 | -------------------------------------------------------------------------------- /webapp/src/boardCloudLimits/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export const LimitUnlimited = 0 5 | 6 | export interface BoardsCloudLimits { 7 | cards: number 8 | used_cards: number 9 | card_limit_timestamp: number 10 | views: number 11 | } 12 | -------------------------------------------------------------------------------- /webapp/src/boardsCloudLimits/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export const LimitUnlimited = 0 5 | 6 | export interface BoardsCloudLimits { 7 | cards: number 8 | used_cards: number 9 | card_limit_timestamp: number 10 | views: number 11 | } 12 | -------------------------------------------------------------------------------- /webapp/src/components/__snapshots__/rootPortal.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/RootPortal should match snapshot 1`] = ` 4 |
7 |
8 |
9 | Testing Portal 10 |
11 |
12 |
13 | `; 14 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blockContent.scss: -------------------------------------------------------------------------------- 1 | .BlockContent { 2 | display: flex; 3 | 4 | &.over-up { 5 | border-top: 1px solid rgba(128, 192, 255, 0.4); 6 | } 7 | 8 | &.over-down { 9 | border-bottom: 1px solid rgba(128, 192, 255, 0.4); 10 | } 11 | 12 | &:hover { 13 | .action { 14 | opacity: 1; 15 | 16 | .AddIcon { 17 | opacity: 0.5; 18 | } 19 | } 20 | } 21 | 22 | .action { 23 | transition: opacity 0.3s; 24 | opacity: 0; 25 | margin: 5px; 26 | } 27 | 28 | .content { 29 | flex-grow: 1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/attachment/attachment.scss: -------------------------------------------------------------------------------- 1 | .Attachment { 2 | display: none; 3 | } 4 | 5 | .AttachmentView { 6 | border: 1px solid #ccc; 7 | border-radius: 5px; 8 | padding: 10px; 9 | margin-bottom: 10px; 10 | } 11 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/checkbox/checkbox.scss: -------------------------------------------------------------------------------- 1 | .Checkbox { 2 | display: flex; 3 | 4 | .inputCheck { 5 | width: auto; 6 | } 7 | 8 | .inputText { 9 | outline: 0; 10 | flex-grow: 1; 11 | } 12 | 13 | } 14 | 15 | .CheckboxView { 16 | display: flex; 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/divider/__snapshots__/divider.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/blocksEditor/blocks/divider should match Display snapshot 1`] = ` 4 |
5 |
8 |
9 | `; 10 | 11 | exports[`components/blocksEditor/blocks/divider should match Input snapshot 1`] = `
`; 12 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/divider/divider.scss: -------------------------------------------------------------------------------- 1 | .Divider { 2 | width: 100%; 3 | margin: 5px 0; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h1/__snapshots__/h1.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/blocksEditor/blocks/h1 should match Display snapshot 1`] = ` 4 |
5 |
6 |

9 | test-value 10 |

11 |
12 |
13 | `; 14 | 15 | exports[`components/blocksEditor/blocks/h1 should match Input snapshot 1`] = ` 16 |
17 | 22 |
23 | `; 24 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h1/h1.scss: -------------------------------------------------------------------------------- 1 | .H1 { 2 | font-size: 32px; 3 | font-weight: 700; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h2/__snapshots__/h2.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/blocksEditor/blocks/h2 should match Display snapshot 1`] = ` 4 |
5 |
6 |

9 | test-value 10 |

11 |
12 |
13 | `; 14 | 15 | exports[`components/blocksEditor/blocks/h2 should match Input snapshot 1`] = ` 16 |
17 | 22 |
23 | `; 24 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h2/h2.scss: -------------------------------------------------------------------------------- 1 | .H2 { 2 | font-size: 24px; 3 | font-weight: 700; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h3/__snapshots__/h3.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/blocksEditor/blocks/h3 should match Display snapshot 1`] = ` 4 |
5 |
6 |

9 | test-value 10 |

11 |
12 |
13 | `; 14 | 15 | exports[`components/blocksEditor/blocks/h3 should match Input snapshot 1`] = ` 16 |
17 | 22 |
23 | `; 24 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/h3/h3.scss: -------------------------------------------------------------------------------- 1 | .H3 { 2 | font-size: 18px; 3 | font-weight: 700; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/image/image.scss: -------------------------------------------------------------------------------- 1 | .Image { 2 | display: none; 3 | } 4 | 5 | .ImageView { 6 | max-width: 400px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/list-item/__snapshots__/list-item.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/blocksEditor/blocks/list-item should match Display snapshot 1`] = ` 4 |
5 |
    6 |
  • 7 | test-value 8 |
  • 9 |
10 |
11 | `; 12 | 13 | exports[`components/blocksEditor/blocks/list-item should match Input snapshot 1`] = ` 14 |
15 |
    16 |
  • 17 | 22 |
  • 23 |
24 |
25 | `; 26 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/list-item/list-item.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/components/blocksEditor/blocks/list-item/list-item.scss -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/quote/quote.scss: -------------------------------------------------------------------------------- 1 | .Editor .Quote input { 2 | width: calc(100% - 80px); 3 | } 4 | 5 | .Quote { 6 | width: 100%; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/text-dev/text.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/components/blocksEditor/blocks/text-dev/text.scss -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/text/text.scss: -------------------------------------------------------------------------------- 1 | .TextContent { 2 | width: 100%; 3 | border: 2px solid #2684ff; 4 | border-radius: 4px; 5 | padding: 10px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/blocks/video/video.scss: -------------------------------------------------------------------------------- 1 | .Video { 2 | display: none; 3 | } 4 | 5 | .VideoView { 6 | max-width: 400px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/components/blocksEditor/editor.scss: -------------------------------------------------------------------------------- 1 | .Editor { 2 | margin-left: 50px; 3 | color: rgb(var(--center-channel-color-rgb)); 4 | background-color: rgb(var(--center-channel-bg-rgb)); 5 | 6 | .RootInput { 7 | display: block; 8 | } 9 | 10 | &.with-content-type { 11 | .RootInput { 12 | display: none; 13 | } 14 | } 15 | 16 | input { 17 | width: 100%; 18 | border: 1px solid hsl(0, 0%, 80%); 19 | border-radius: 4px; 20 | padding: 3px 6px; 21 | outline: 0; 22 | 23 | &:focus { 24 | border: 2px solid #2684ff; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /webapp/src/components/boardTemplateSelector/boardTemplateSelectorPreview.scss: -------------------------------------------------------------------------------- 1 | .BoardTemplateSelectorPreview { 2 | position: relative; 3 | transform-origin: top left; 4 | transform: scale(0.8); 5 | width: 126%; 6 | height: 480px; 7 | border-radius: var(--modal-rad); 8 | pointer-events: none; 9 | 10 | .ButtonWithMenu { 11 | display: none; 12 | } 13 | 14 | .Kanban { 15 | overflow: hidden; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/components/cardActionsMenu/cardActionsMenuIcon.scss: -------------------------------------------------------------------------------- 1 | .CardActionsMenuIcon { 2 | border-radius: 3px; 3 | padding: 0; 4 | box-shadow: rgba(var(--center-channel-color-rgb), 0.1) 0 0 0 1px, 5 | rgba(var(--center-channel-color-rgb), 0.1) 0 2px 4px; 6 | height: 24px; 7 | width: 24px; 8 | 9 | &:hover { 10 | background: rgb(var(--center-channel-color-rgb), 0.1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /webapp/src/components/cardActionsMenu/cardActionsMenuIcon.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import OptionsIcon from '../../widgets/icons/options' 7 | import IconButton from '../../widgets/buttons/iconButton' 8 | 9 | import './cardActionsMenuIcon.scss' 10 | 11 | const CardActionsMenuIcon = () => { 12 | return ( 13 | } 16 | /> 17 | ) 18 | } 19 | 20 | export default CardActionsMenuIcon 21 | -------------------------------------------------------------------------------- /webapp/src/components/cardBadges.scss: -------------------------------------------------------------------------------- 1 | .CardBadges { 2 | display: flex; 3 | align-items: center; 4 | margin-top: 4px; 5 | height: 24px; 6 | 7 | span { 8 | display: flex; 9 | align-items: center; 10 | margin-right: 4px; 11 | 12 | .Icon, 13 | .CompassIcon { 14 | color: rgba(var(--center-channel-color-rgb), 0.64); 15 | fill: currentColor; 16 | margin-right: 4px; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /webapp/src/components/cardLimitNotification.scss: -------------------------------------------------------------------------------- 1 | .NotifyAdminSuccessNotify { 2 | position: fixed; 3 | bottom: 173px; 4 | height: unset; 5 | 6 | .NotificationBox__icon { 7 | font-size: 24px; 8 | 9 | svg { 10 | stroke: var(--online-indicator); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /webapp/src/components/content/__snapshots__/contentElement.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/content/contentElement should match snapshot for checkbox type 1`] = ` 4 |
5 |
8 | 13 | 20 |
21 |
22 | `; 23 | -------------------------------------------------------------------------------- /webapp/src/components/content/__snapshots__/dividerElement.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/content/DividerElement should match snapshot 1`] = ` 4 |
5 |
8 |
9 | `; 10 | -------------------------------------------------------------------------------- /webapp/src/components/content/__snapshots__/textElement.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/content/TextElement return a textElement 1`] = ` 4 |
5 |
8 |
11 |
15 |
16 |
17 |
18 | `; 19 | -------------------------------------------------------------------------------- /webapp/src/components/content/archivedFile/__snapshots__/archivedFile.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/content/archivedFile should match snapshot 1`] = ` 4 |
5 |
8 | 11 | 25 |
26 |
27 | `; 28 | -------------------------------------------------------------------------------- /webapp/src/components/content/checkboxElement.scss: -------------------------------------------------------------------------------- 1 | .CheckboxElement { 2 | display: flex; 3 | align-items: center; 4 | min-height: 34px; 5 | 6 | input { 7 | margin-right: 10px; 8 | } 9 | 10 | .Editable { 11 | width: 100%; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /webapp/src/components/content/dividerElement.scss: -------------------------------------------------------------------------------- 1 | .DividerElement { 2 | padding-top: 16px; 3 | border-bottom: 1px solid rgba(var(--center-channel-color-rgb), 0.09); 4 | margin-bottom: 17px; 5 | flex-grow: 1; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/components/content/dividerElement.test.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | import {render} from '@testing-library/react' 6 | 7 | import {wrapIntl} from '../../testUtils' 8 | 9 | import DividerElement from './dividerElement' 10 | 11 | describe('components/content/DividerElement', () => { 12 | test('should match snapshot', async () => { 13 | const component = wrapIntl() 14 | const {container} = render(component) 15 | expect(container).toMatchSnapshot() 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /webapp/src/components/content/textElement.scss: -------------------------------------------------------------------------------- 1 | .TextElement { 2 | display: inline; 3 | 4 | .markdown-editor-error { 5 | background-color: rgba(210, 75, 78, 0.08); 6 | border: 1px solid var(--error-text); 7 | } 8 | 9 | .error-message { 10 | color: var(--dnd-indicator, rgba(210, 75, 78, 1)); 11 | margin: 16px 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /webapp/src/components/globalHeader/globalHeaderSettingsMenu.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/components/globalHeader/globalHeaderSettingsMenu.scss -------------------------------------------------------------------------------- /webapp/src/components/guestNoBoards.scss: -------------------------------------------------------------------------------- 1 | .GuestNoBoards { 2 | height: 100%; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | 7 | > div { 8 | display: flex; 9 | align-items: center; 10 | flex-direction: column; 11 | justify-content: center; 12 | text-align: center; 13 | } 14 | 15 | .title { 16 | font-size: 52px; 17 | font-weight: 400; 18 | } 19 | 20 | .subtitle { 21 | font-size: 20px; 22 | margin: 16px 0; 23 | } 24 | 25 | svg { 26 | margin: 56px 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /webapp/src/components/hiddenCardCount/hiddenCardCount.scss: -------------------------------------------------------------------------------- 1 | .HiddenCardCount { 2 | display: flex; 3 | height: 30px; 4 | 5 | &:hover { 6 | cursor: pointer; 7 | } 8 | 9 | .hidden-card-title { 10 | background: rgba(243, 192, 199, 0.2); 11 | color: #d24b4e; 12 | padding: 3px 6px; 13 | border-radius: 4px; 14 | text-transform: uppercase; 15 | font-weight: bold; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/components/kanban/__snapshots__/kanbanColumn.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`src/components/kanban/kanbanColumn should match snapshot 1`] = ` 4 |
5 |
8 |
9 | `; 10 | -------------------------------------------------------------------------------- /webapp/src/components/kanban/calculation/__snapshots__/kanbanOption.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/kanban/calculations/Option base case 1`] = ` 4 |
5 |
8 | 9 | Count Unique Values 10 | 11 | 14 | 15 |
16 |
17 | `; 18 | -------------------------------------------------------------------------------- /webapp/src/components/kanban/calculation/calculation.scss: -------------------------------------------------------------------------------- 1 | .KanbanCalculation { 2 | position: relative; 3 | 4 | button { 5 | cursor: pointer !important; 6 | height: 24px; 7 | padding: 0 6px; 8 | min-width: 24px; 9 | 10 | span { 11 | max-width: 35px; 12 | overflow: hidden; 13 | text-overflow: ellipsis; 14 | white-space: nowrap; 15 | } 16 | 17 | &:hover { 18 | background-color: rgba(var(--center-channel-color-rgb), 0.1); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /webapp/src/components/kanban/kanbanColumn.scss: -------------------------------------------------------------------------------- 1 | .octo-board-column { 2 | &.dragover { 3 | background-color: rgba(128, 192, 255, 0.15); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /webapp/src/components/live-markdown-plugin/utils/findRangesWithRegex.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | const findRangesWithRegex = (text: string, regex: RegExp): number[][] => { 4 | const ranges: number[][] = [] 5 | let matches 6 | 7 | do { 8 | matches = regex.exec(text) 9 | if (matches) { 10 | ranges.push([matches.index, (matches.index + matches[0].length) - 1]) 11 | } 12 | } while (matches) 13 | 14 | return ranges 15 | } 16 | 17 | export default findRangesWithRegex 18 | -------------------------------------------------------------------------------- /webapp/src/components/markdownEditorInput/entryComponent/entryComponent.scss: -------------------------------------------------------------------------------- 1 | .EntryComponent { 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-between; 5 | width: 100%; 6 | 7 | .EntryComponent__left { 8 | display: flex; 9 | align-items: center; 10 | } 11 | 12 | .EntryComponent__hint { 13 | opacity: 0.56; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/components/modalWrapper.scss: -------------------------------------------------------------------------------- 1 | .ModalWrapper { 2 | position: relative; 3 | overflow: unset; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/components/modalWrapper.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import React from 'react' 4 | import './modalWrapper.scss' 5 | 6 | type Props = { 7 | children: React.ReactNode 8 | } 9 | 10 | const ModalWrapper = (props: Props) => { 11 | return ( 12 |
13 | {props.children} 14 |
15 | ) 16 | } 17 | 18 | export default React.memo(ModalWrapper) 19 | -------------------------------------------------------------------------------- /webapp/src/components/newVersionBanner.scss: -------------------------------------------------------------------------------- 1 | .NewVersionBanner { 2 | background-color: var(--prop-blue); 3 | text-align: center; 4 | padding: 10px; 5 | } 6 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/addComments/add_comments.scss: -------------------------------------------------------------------------------- 1 | .AddCommentTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: 170px; 4 | top: 18px; 5 | } 6 | 7 | .tippy-arrow { 8 | top: -21px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | top: 24px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/addDescription/add_description.scss: -------------------------------------------------------------------------------- 1 | .AddDescriptionTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | top: -10px; 4 | left: calc(120px + 20%); 5 | } 6 | 7 | .tippy-arrow { 8 | left: 21px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | left: -21px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/addProperties/add_properties.scss: -------------------------------------------------------------------------------- 1 | .AddPropertiesTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: 100%; 4 | top: calc(50% - 6px); 5 | } 6 | 7 | .tippy-arrow { 8 | top: -21px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | top: 24px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/addView/add_view.scss: -------------------------------------------------------------------------------- 1 | .AddViewTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: 91%; 4 | top: 100%; 5 | } 6 | 7 | .tippy-arrow { 8 | left: 21px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | right: 22px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/copyLink/copy_link.scss: -------------------------------------------------------------------------------- 1 | .CopyLinkTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: calc(100% - 6px); 4 | top: 18px; 5 | } 6 | 7 | .tippy-arrow { 8 | top: 21px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | top: -24px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/manageCategories/manageCategories.scss: -------------------------------------------------------------------------------- 1 | .ManageCatergoies { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | margin-left: 14px; 4 | margin-top: 5px; 5 | } 6 | 7 | .tutorial-tour-tip__overlay { 8 | cursor: pointer; 9 | } 10 | 11 | .tutorial-tour-tip__footer { 12 | margin-top: 15px; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/openCard/open_card.scss: -------------------------------------------------------------------------------- 1 | .OpenCardTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: 80%; 4 | top: calc(100% - 6px); 5 | } 6 | 7 | .tutorial-tour-tip__overlay { 8 | cursor: pointer; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/searchForBoards/searchForBoards.scss: -------------------------------------------------------------------------------- 1 | .SearchForBoards { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | margin-top: 10px; 4 | } 5 | 6 | .tutorial-tour-tip__overlay { 7 | cursor: pointer; 8 | } 9 | 10 | .tutorial-tour-tip__footer { 11 | margin-top: 15px; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/shareBoard/shareBoard.scss: -------------------------------------------------------------------------------- 1 | .ShareBoardTourStep { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | left: calc(80% - 16px); 4 | top: 27px; 5 | } 6 | 7 | .tippy-arrow { 8 | left: -20px !important; 9 | } 10 | 11 | &.tippy-box.tutorial-tour-tip__box { 12 | right: -22px; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/components/onboardingTour/sidebarCategories/sidebarCategories.scss: -------------------------------------------------------------------------------- 1 | .SidebarCategories { 2 | &.tutorial-tour-tip__pulsating-dot-ctr { 3 | margin-left: 135px; 4 | margin-top: -10px; 5 | } 6 | 7 | .tutorial-tour-tip__overlay { 8 | cursor: pointer; 9 | } 10 | 11 | .tutorial-tour-tip__footer { 12 | margin-top: 15px; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/components/shareBoard/__snapshots__/shareBoardLoginButton.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`src/components/shareBoard/shareBoardLoginButton should match snapshot 1`] = ` 4 |
5 |
8 | 17 |
18 |
19 | `; 20 | -------------------------------------------------------------------------------- /webapp/src/components/shareBoard/shareBoardButton.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/components/shareBoard/shareBoardButton.scss -------------------------------------------------------------------------------- /webapp/src/components/shareBoard/shareBoardLoginButton.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/components/shareBoard/shareBoardLoginButton.scss -------------------------------------------------------------------------------- /webapp/src/components/sidebar/__snapshots__/deleteBoardDialog.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`components/sidebar/DeleteBoardDialog Cancel should not submit 1`] = ` 4 |
7 | exists 8 |
9 | `; 10 | 11 | exports[`components/sidebar/DeleteBoardDialog Delete should submit 1`] = ` 12 |
15 | deleted 16 |
17 | `; 18 | -------------------------------------------------------------------------------- /webapp/src/components/sidebar/sidebarSettingsMenu.scss: -------------------------------------------------------------------------------- 1 | .SidebarSettingsMenu { 2 | .menu-entry { 3 | display: flex; 4 | cursor: pointer; 5 | flex-direction: row; 6 | padding: 0 16px 0 8px; 7 | height: 36px; 8 | align-items: center; 9 | padding-left: 20px; 10 | color: rgba(var(--sidebar-text-rgb), 0.64); 11 | font-weight: 400; 12 | 13 | &:hover { 14 | background-color: rgba(var(--sidebar-text-rgb), 0.08); 15 | display: flex; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /webapp/src/components/table/horizontalGrip.scss: -------------------------------------------------------------------------------- 1 | .HorizontalGrip { 2 | width: 5px; 3 | cursor: ew-resize; 4 | flex-shrink: 0; 5 | 6 | &:hover { 7 | background-color: rgba(90, 192, 255, 0.7); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /webapp/src/components/viewHeader/filterComponent.scss: -------------------------------------------------------------------------------- 1 | .FilterComponent { 2 | min-width: 430px; 3 | } 4 | -------------------------------------------------------------------------------- /webapp/src/components/viewHeader/filterEntry.scss: -------------------------------------------------------------------------------- 1 | .FilterEntry { 2 | display: flex; 3 | flex-direction: row; 4 | 5 | > div { 6 | display: flex; 7 | flex-direction: row; 8 | } 9 | 10 | .Button { 11 | overflow: hidden; 12 | max-width: 220px; 13 | text-overflow: ellipsis; 14 | white-space: normal; 15 | display: block; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/components/viewHeader/filterValue.scss: -------------------------------------------------------------------------------- 1 | .filterValue { 2 | .Menu { 3 | max-height: 400px; 4 | overflow-y: auto; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/components/viewMenu.scss: -------------------------------------------------------------------------------- 1 | .ViewMenu { 2 | 3 | margin-top: -200px; 4 | 5 | .view-list { 6 | max-height: 30vh; 7 | overflow-y: auto; 8 | height: auto; 9 | } 10 | 11 | .subMenu { 12 | height: 100%; 13 | overflow: visible; 14 | } 15 | 16 | @media (max-height: 370px) { 17 | margin-top: -230px; 18 | 19 | .subMenu { 20 | height: 50px; 21 | overflow-y: scroll; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /webapp/src/config/clientConfig.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export type ClientConfig = { 5 | telemetry: boolean 6 | telemetryid: string 7 | enablePublicSharedBoards: boolean 8 | featureFlags: Record 9 | teammateNameDisplay: string 10 | maxFileSize: number 11 | } 12 | -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-Light.woff2 -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-LightItalic.woff2 -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-Regular.woff2 -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-RegularItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-RegularItalic.woff2 -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-SemiBold.woff2 -------------------------------------------------------------------------------- /webapp/src/fonts/metropolis/Metropolis-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/fonts/metropolis/Metropolis-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /webapp/src/insights/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export type TopBoard = { 5 | boardID: string 6 | icon: string 7 | title: string 8 | activityCount: number 9 | activeUsers: string 10 | createdBy: string 11 | } 12 | 13 | export type TopBoardResponse = { 14 | has_next: boolean 15 | items: TopBoard[] 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/onboardingTour/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export interface PrepareOnboardingResponse { 5 | teamID: string 6 | boardID: string 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/pages/errorPage.scss: -------------------------------------------------------------------------------- 1 | .ErrorPage { 2 | height: 100%; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | 7 | > div { 8 | display: flex; 9 | align-items: center; 10 | flex-direction: column; 11 | justify-content: center; 12 | text-align: center; 13 | } 14 | 15 | .title { 16 | font-size: 52px; 17 | font-weight: 400; 18 | } 19 | 20 | .subtitle { 21 | font-size: 20px; 22 | margin: 16px 0; 23 | } 24 | 25 | svg { 26 | margin: 56px 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /webapp/src/properties/createdBy/createdBy.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import Person from '../person/person' 7 | import {PropertyProps} from '../types' 8 | 9 | const CreatedBy = (props: PropertyProps): JSX.Element => { 10 | return ( 11 | 16 | ) 17 | } 18 | 19 | export default CreatedBy 20 | -------------------------------------------------------------------------------- /webapp/src/properties/createdTime/createdTime.scss: -------------------------------------------------------------------------------- 1 | .CreatedTime { 2 | display: flex; 3 | align-items: center; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/properties/email/property.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {IntlShape} from 'react-intl' 4 | 5 | import {PropertyType, PropertyTypeEnum, FilterValueType} from '../types' 6 | 7 | import Email from './email' 8 | 9 | export default class EmailProperty extends PropertyType { 10 | Editor = Email 11 | name = 'Email' 12 | type = 'email' as PropertyTypeEnum 13 | displayName = (intl: IntlShape) => intl.formatMessage({id: 'PropertyType.Email', defaultMessage: 'Email'}) 14 | canFilter = true 15 | filterValueType = 'text' as FilterValueType 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/properties/multiperson/multiperson.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import {PropertyProps} from '../types' 7 | import ConfirmPerson from '../person/confirmPerson' 8 | 9 | const MultiPerson = (props: PropertyProps): JSX.Element => { 10 | return ( 11 | 15 | ) 16 | } 17 | 18 | export default MultiPerson 19 | -------------------------------------------------------------------------------- /webapp/src/properties/multiselect/__snapshots__/multiselect.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`properties/multiSelect shows only the selected options when menu is not opened 1`] = ` 4 |
5 |
10 | 13 | a 14 | 15 | 18 | b 19 | 20 |
21 |
22 | `; 23 | -------------------------------------------------------------------------------- /webapp/src/properties/number/__snapshots__/number.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`properties/number should match snapshot for number with empty value 1`] = ` 4 |
5 | 12 |
13 | `; 14 | -------------------------------------------------------------------------------- /webapp/src/properties/number/number.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import {PropertyProps} from '../types' 7 | import BaseTextEditor from '../baseTextEditor' 8 | 9 | const Number = (props: PropertyProps): JSX.Element => { 10 | return ( 11 | props.propertyValue === '' || !isNaN(parseInt(props.propertyValue as string, 10))} 14 | /> 15 | ) 16 | } 17 | export default Number 18 | -------------------------------------------------------------------------------- /webapp/src/properties/person/person.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import {PropertyProps} from '../types' 7 | 8 | import ConfirmPerson from './confirmPerson' 9 | 10 | const Person = (props: PropertyProps): JSX.Element => { 11 | return ( 12 | 16 | ) 17 | } 18 | 19 | export default Person 20 | -------------------------------------------------------------------------------- /webapp/src/properties/phone/phone.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import {PropertyProps} from '../types' 7 | import BaseTextEditor from '../baseTextEditor' 8 | 9 | const Phone = (props: PropertyProps): JSX.Element => { 10 | return ( 11 | true} 14 | /> 15 | ) 16 | } 17 | export default Phone 18 | -------------------------------------------------------------------------------- /webapp/src/properties/phone/property.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {IntlShape} from 'react-intl' 4 | 5 | import {PropertyType, PropertyTypeEnum, FilterValueType} from '../types' 6 | 7 | import Phone from './phone' 8 | 9 | export default class PhoneProperty extends PropertyType { 10 | Editor = Phone 11 | name = 'Phone' 12 | type = 'phone' as PropertyTypeEnum 13 | displayName = (intl: IntlShape) => intl.formatMessage({id: 'PropertyType.Phone', defaultMessage: 'Phone'}) 14 | canFilter = true 15 | filterValueType = 'text' as FilterValueType 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/properties/text/property.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {IntlShape} from 'react-intl' 4 | 5 | import {PropertyType, PropertyTypeEnum, FilterValueType} from '../types' 6 | 7 | import Text from './text' 8 | 9 | export default class TextProperty extends PropertyType { 10 | Editor = Text 11 | name = 'Text' 12 | type = 'text' as PropertyTypeEnum 13 | displayName = (intl: IntlShape) => intl.formatMessage({id: 'PropertyType.Text', defaultMessage: 'Text'}) 14 | canFilter = true 15 | filterValueType = 'text' as FilterValueType 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/properties/text/text.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import {PropertyProps} from '../types' 7 | import BaseTextEditor from '../baseTextEditor' 8 | 9 | const Text = (props: PropertyProps): JSX.Element => { 10 | return ( 11 | true} 14 | spellCheck={true} 15 | /> 16 | ) 17 | } 18 | export default Text 19 | -------------------------------------------------------------------------------- /webapp/src/properties/unknown/property.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {IntlShape} from 'react-intl' 4 | 5 | import Text from '../text/text' 6 | import {PropertyType, PropertyTypeEnum} from '../types' 7 | 8 | export default class UnkownProperty extends PropertyType { 9 | Editor = Text 10 | name = 'Text' 11 | type = 'unknown' as PropertyTypeEnum 12 | displayName = (intl: IntlShape) => intl.formatMessage({id: 'PropertyType.Unknown', defaultMessage: 'Unknown'}) 13 | } 14 | -------------------------------------------------------------------------------- /webapp/src/properties/updatedBy/__snapshots__/updatedBy.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`properties/updatedBy should match snapshot 1`] = ` 4 |
5 |
8 |
11 | username_1 12 |
13 |
14 |
15 | `; 16 | -------------------------------------------------------------------------------- /webapp/src/properties/updatedBy/updatedBy.scss: -------------------------------------------------------------------------------- 1 | .LastModifiedBy { 2 | display: flex; 3 | align-items: center; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/properties/updatedTime/__snapshots__/updatedTime.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`properties/updatedTime should match snapshot 1`] = ` 4 |
5 |
8 | June 15, 2021 at 4:22 PM 9 |
10 |
11 | `; 12 | -------------------------------------------------------------------------------- /webapp/src/properties/updatedTime/updatedTime.scss: -------------------------------------------------------------------------------- 1 | .UpdatedTime { 2 | display: flex; 3 | align-items: center; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/properties/url/property.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import {IntlShape} from 'react-intl' 4 | 5 | import {PropertyType, PropertyTypeEnum, FilterValueType} from '../types' 6 | 7 | import Url from './url' 8 | 9 | export default class UrlProperty extends PropertyType { 10 | Editor = Url 11 | name = 'Url' 12 | type = 'url' as PropertyTypeEnum 13 | displayName = (intl: IntlShape) => intl.formatMessage({id: 'PropertyType.Url', defaultMessage: 'URL'}) 14 | canFilter = true 15 | filterValueType = 'text' as FilterValueType 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/statistics/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export interface BoardSiteStatistics { 5 | board_count: number 6 | card_count: number 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/store/hooks.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import {TypedUseSelectorHook, useDispatch, useSelector} from 'react-redux' 5 | 6 | import type {RootState, AppDispatch} from '.' 7 | 8 | export const useAppDispatch = () => useDispatch() 9 | export const useAppSelector: TypedUseSelectorHook = useSelector 10 | -------------------------------------------------------------------------------- /webapp/src/styles/_markdown.scss: -------------------------------------------------------------------------------- 1 | .markdown__table { 2 | margin: 5px 0 10px; 3 | background: var(--center-channel-bg); 4 | border-collapse: collapse; 5 | 6 | th, 7 | td { 8 | padding: 6px 13px; 9 | border: 1px solid #ddd; 10 | } 11 | 12 | a { 13 | white-space: nowrap; 14 | word-break: initial; 15 | } 16 | 17 | tbody tr { 18 | background: var(--center-channel-bg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /webapp/src/styles/shared-variables.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --center-channel-bg-rgb: 255, 255, 255; 3 | --center-channel-color-rgb: 63, 67, 80; 4 | --sidebar-bg-rgb: 30, 50, 92; 5 | --sidebar-text-rgb: 255, 255, 255; 6 | --button-color-rgb: 255, 255, 255; 7 | --button-bg-rgb: 28, 88, 217; 8 | --button-danger-color-rgb: 255, 255, 255; 9 | --button-danger-bg-rgb: 210, 75, 78; 10 | --link-color-rgb: 56, 111, 229; 11 | --error-text-rgb: #d24b4e; 12 | } 13 | -------------------------------------------------------------------------------- /webapp/src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | @import './shared-variables'; 2 | @import './focalboard-variables'; 3 | -------------------------------------------------------------------------------- /webapp/src/telemetry/telemetry.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export interface TelemetryHandler { 5 | trackEvent: (userId: string, userRoles: string, category: string, event: string, props?: any) => void 6 | pageVisited: (userId: string, userRoles: string, category: string, name: string) => void 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/test/fetchMock.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | class FetchMock { 5 | static fn = jest.fn(async () => { 6 | const response = new Response() 7 | return response 8 | }) 9 | 10 | static async jsonResponse(json: string): Promise { 11 | const response = new Response(json) 12 | return response 13 | } 14 | } 15 | 16 | export {FetchMock} 17 | -------------------------------------------------------------------------------- /webapp/src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "*": [ 7 | "../node_modules/*", 8 | "../@custom_types/*" 9 | ] 10 | } 11 | }, 12 | "include": [ 13 | "./**/*.ts", 14 | "./**/*.tsx" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/types/images.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | declare module '*.jpg'; 5 | declare module '*.png'; 6 | declare module '*.gif'; 7 | declare module '*.apng'; 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/__snapshots__/guestBadge.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`widgets/guestBadge should match the snapshot on show 1`] = ` 4 |
5 |
8 |
11 | Guest 12 |
13 |
14 |
15 | `; 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/adminBadge/__snapshots__/adminBadge.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`widgets/adminBadge should match the snapshot for Admin 1`] = ` 4 |
5 |
8 |
11 | Admin 12 |
13 |
14 |
15 | `; 16 | 17 | exports[`widgets/adminBadge should match the snapshot for TeamAdmin 1`] = ` 18 |
19 |
22 |
25 | Team Admin 26 |
27 |
28 |
29 | `; 30 | -------------------------------------------------------------------------------- /webapp/src/widgets/adminBadge/adminBadge.scss: -------------------------------------------------------------------------------- 1 | .AdminBadge { 2 | display: inline-flex; 3 | align-items: center; 4 | margin: 0 10px 0 4px; 5 | } 6 | 7 | .AdminBadge__box { 8 | padding: 2px 4px; 9 | border: 0; 10 | background: rgba(var(--center-channel-color-rgb), 0.16); 11 | border-radius: 2px; 12 | font-family: inherit; 13 | font-size: 10px; 14 | font-weight: 600; 15 | line-height: 14px; 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/widgets/editable.scss: -------------------------------------------------------------------------------- 1 | .Editable { 2 | cursor: text; 3 | overflow: hidden; 4 | text-overflow: ellipsis; 5 | border: 1px solid transparent; 6 | min-height: 24px; 7 | 8 | &.active { 9 | min-width: 100px; 10 | } 11 | 12 | &::placeholder { 13 | color: rgba(var(--center-channel-color-rgb), 0.4); 14 | opacity: 1; 15 | } 16 | 17 | &.error { 18 | border: 1px solid rgb(var(--error-text-rgb)); 19 | border-radius: var(--default-rad); 20 | } 21 | 22 | &.readonly { 23 | background-color: transparent; 24 | flex: 1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /webapp/src/widgets/editableArea.scss: -------------------------------------------------------------------------------- 1 | .EditableAreaWrap { 2 | width: 100%; 3 | } 4 | 5 | .EditableArea { 6 | resize: none; 7 | } 8 | 9 | .EditableAreaContainer { 10 | height: 0; 11 | overflow: hidden; 12 | } 13 | 14 | .EditableAreaReference { 15 | height: auto; 16 | width: 100%; 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/guestBadge.scss: -------------------------------------------------------------------------------- 1 | .GuestBadge { 2 | display: inline-flex; 3 | align-items: center; 4 | margin: 0 10px 0 4px; 5 | } 6 | 7 | .GuestBadge__box { 8 | padding: 2px 4px; 9 | border: 0; 10 | background: rgba(var(--center-channel-color-rgb), 0.16); 11 | border-radius: 2px; 12 | font-family: inherit; 13 | font-size: 10px; 14 | font-weight: 600; 15 | line-height: 14px; 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/HandRight.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function HandRight(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/Link.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './link.scss' 9 | 10 | export default function LinkIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/add.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/widgets/icons/add.scss -------------------------------------------------------------------------------- /webapp/src/widgets/icons/add.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './add.scss' 9 | 10 | export default function AddIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/alert.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function AlertIcon(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/apps.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function Apps(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/board.scss: -------------------------------------------------------------------------------- 1 | .BoardIcon { 2 | stroke-width: 8px; 3 | } 4 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/brokenFile.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function BrokenFile(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/calendar.scss: -------------------------------------------------------------------------------- 1 | .CalendarIcon { 2 | stroke-width: 8px; 3 | } 4 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/card.scss: -------------------------------------------------------------------------------- 1 | .CardIcon { 2 | stroke-width: 6px; 3 | } 4 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/check.scss: -------------------------------------------------------------------------------- 1 | .CheckIcon { 2 | stroke: currentColor; 3 | stroke-width: 8px; 4 | fill: none; 5 | width: 1em; 6 | height: 1em; 7 | line-height: 1em; 8 | } 9 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/check.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './check.scss' 7 | 8 | export default function CheckIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/checkIcon.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | // TODO use this icon instead of check.tsx 9 | export default function Check(): JSX.Element { 10 | return ( 11 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/chevronDown.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function ChevronDown(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/chevronRight.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function ChevronRight(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/chevronUp.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function ChevronUp(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/close.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function CloseIcon(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/closeCircle.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './add.scss' 9 | 10 | export default function CloseCircle(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/compassIcon.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | type Props = { 7 | icon: string 8 | className?: string 9 | } 10 | 11 | export default function CompassIcon(props: Props): JSX.Element { 12 | // All compass icon classes start with icon, 13 | // so not expecting that prefix in props. 14 | return ( 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/delete.scss: -------------------------------------------------------------------------------- 1 | .DeleteIcon { 2 | fill: rgba(var(--center-channel-color-rgb), 0.5); 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/delete.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './delete.scss' 9 | 10 | export default function DeleteIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/disclosureTriangle.scss: -------------------------------------------------------------------------------- 1 | .DisclosureTriangleIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/disclosureTriangle.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './disclosureTriangle.scss' 7 | 8 | export default function DisclosureTriangle(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/divider.scss: -------------------------------------------------------------------------------- 1 | .DividerIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/dot.scss: -------------------------------------------------------------------------------- 1 | .DotIcon { 2 | fill: rgba(var(--center-channel-color-rgb), 0.5); 3 | width: 24px; 4 | height: 24px; 5 | } 6 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/dot.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './dot.scss' 7 | 8 | export default function DotIcon(): JSX.Element { 9 | return ( 10 | 15 | 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/dropdown.scss: -------------------------------------------------------------------------------- 1 | .DropdownIcon { 2 | color: rgb(var(--center-channel-color-rgb)); 3 | font-size: 16px; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/dropdown.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './dropdown.scss' 9 | 10 | export default function DropdownIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/duplicate.scss: -------------------------------------------------------------------------------- 1 | .DuplicateIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/duplicate.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './duplicate.scss' 9 | 10 | export default function DuplicateIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/edit.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function EditIcon(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/emoji.scss: -------------------------------------------------------------------------------- 1 | .EmojiIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/focalboard_logo.scss: -------------------------------------------------------------------------------- 1 | .FocalboardLogoIcon { 2 | width: 32px; 3 | height: 32px; 4 | fill: rgba(var(--sidebar-text-rgb), 0.7); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/folder.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function Folder(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/gallery.scss: -------------------------------------------------------------------------------- 1 | .GalleryIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/globe.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function Globe(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/grip.scss: -------------------------------------------------------------------------------- 1 | .GripIcon { 2 | fill: rgb(var(--center-channel-color-rgb), 0.5); 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/hamburger.scss: -------------------------------------------------------------------------------- 1 | .HamburgerIcon { 2 | stroke: rgba(var(--center-channel-color-rgb), 0.5); 3 | stroke-width: 6px; 4 | fill: none; 5 | width: 24px; 6 | height: 24px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/hamburger.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './hamburger.scss' 7 | 8 | export default function HamburgerIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/help.scss: -------------------------------------------------------------------------------- 1 | .HelpIcon { 2 | color: rgba(var(--sidebar-text-rgb), 0.7); 3 | font-size: 16px; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/help.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import React from 'react' 4 | 5 | import CompassIcon from './compassIcon' 6 | 7 | import './help.scss' 8 | 9 | export default function HelpIcon(): JSX.Element { 10 | return ( 11 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/hide.scss: -------------------------------------------------------------------------------- 1 | .HideIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/hideSidebar.scss: -------------------------------------------------------------------------------- 1 | .HideSidebarIcon { 2 | stroke: rgba(var(--center-channel-color-rgb), 0.5); 3 | stroke-width: 6px; 4 | fill: none; 5 | width: 24px; 6 | height: 24px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/hideSidebar.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './hideSidebar.scss' 7 | 8 | export default function HideSidebarIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/image.scss: -------------------------------------------------------------------------------- 1 | .ImageIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/link.scss: -------------------------------------------------------------------------------- 1 | 2 | .LinkIcon { 3 | color: rgba(var(--body-color), 0.5); 4 | font-size: 18px; 5 | width: 16px; 6 | 7 | &::before { 8 | margin: 0 !important; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/lockOutline.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function LockOutline(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/logo.scss: -------------------------------------------------------------------------------- 1 | .LogoIcon { 2 | font-size: 16px; 3 | color: rgba(var(--sidebar-text-rgb), 0.7); 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/logo.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './logo.scss' 7 | import CompassIcon from './compassIcon' 8 | 9 | export default function LogoIcon(): JSX.Element { 10 | return ( 11 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/logoWithName.scss: -------------------------------------------------------------------------------- 1 | .LogoWithNameIcon { 2 | width: 150px; 3 | height: 32px; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/logoWithNameWhite.scss: -------------------------------------------------------------------------------- 1 | .LogoWithNameWhiteIcon { 2 | width: 150px; 3 | height: 32px; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/message.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function MessageIcon(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/newFolder.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function CreateNewFolder(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/options.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/widgets/icons/options.scss -------------------------------------------------------------------------------- /webapp/src/widgets/icons/options.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './options.scss' 9 | 10 | export default function OptionsIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/random.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function RandomIcon(): JSX.Element { 9 | return ( 10 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/search.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function Search(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/settings.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/src/widgets/icons/settings.scss -------------------------------------------------------------------------------- /webapp/src/widgets/icons/settings.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | import './settings.scss' 9 | 10 | export default function SettingsIcon(): JSX.Element { 11 | return ( 12 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/show.scss: -------------------------------------------------------------------------------- 1 | .ShowIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/showSidebar.scss: -------------------------------------------------------------------------------- 1 | .ShowSidebarIcon { 2 | stroke: rgba(var(--center-channel-color-rgb), 0.5); 3 | stroke-width: 6px; 4 | fill: none; 5 | width: 24px; 6 | height: 24px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/showSidebar.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './showSidebar.scss' 7 | 8 | export default function ShowSidebarIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/sortDown.scss: -------------------------------------------------------------------------------- 1 | .SortDownIcon { 2 | stroke: rgba(var(--center-channel-color-rgb), 0.5); 3 | stroke-width: 8px; 4 | fill: none; 5 | width: 24px; 6 | height: 24px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/sortDown.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './sortDown.scss' 7 | 8 | export default function SortDownIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/sortUp.scss: -------------------------------------------------------------------------------- 1 | .SortUpIcon { 2 | stroke: currentColor; 3 | stroke-width: 8px; 4 | fill: none; 5 | width: 24px; 6 | height: 24px; 7 | } 8 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/sortUp.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './sortUp.scss' 7 | 8 | export default function SortUpIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/submenuTriangle.scss: -------------------------------------------------------------------------------- 1 | .SubmenuTriangleIcon { 2 | fill: currentColor; 3 | stroke: none; 4 | width: 24px; 5 | height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/submenuTriangle.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import './submenuTriangle.scss' 7 | 8 | export default function SubmenuTriangleIcon(): JSX.Element { 9 | return ( 10 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/table.scss: -------------------------------------------------------------------------------- 1 | .TableIcon { 2 | stroke-width: 8px; 3 | } 4 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/text.scss: -------------------------------------------------------------------------------- 1 | .TextIcon { 2 | stroke: none; 3 | width: 1em; 4 | height: 1em; 5 | line-height: 1em; 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/icons/update.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import React from 'react' 5 | 6 | import CompassIcon from './compassIcon' 7 | 8 | export default function Update(): JSX.Element { 9 | return ( 10 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/colorOption.scss: -------------------------------------------------------------------------------- 1 | .ColorOption { 2 | .menu-colorbox { 3 | display: inline-block; 4 | margin-right: 8px; 5 | vertical-align: middle; 6 | width: 18px; 7 | height: 18px; 8 | border-radius: 3px; 9 | box-shadow: rgba(15, 15, 15, 0.1) 0 0 0 1px inset; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | import Menu from './menu' 5 | 6 | export default Menu 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/labelOption.scss: -------------------------------------------------------------------------------- 1 | .Menu { 2 | .LabelOption.menu-option { 3 | cursor: auto; 4 | pointer-events: none; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/menuItem.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | 4 | export type MenuOptionProps = { 5 | id: string 6 | name: string 7 | onClick: (id: string) => void 8 | } 9 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/separatorOption.scss: -------------------------------------------------------------------------------- 1 | .MenuSeparator { 2 | border-bottom: solid 1px rgba(var(--center-channel-color-rgb), 0.16); 3 | margin: 8px 0; 4 | } 5 | -------------------------------------------------------------------------------- /webapp/src/widgets/menu/separatorOption.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | import React, {FC} from 'react' 4 | 5 | import './separatorOption.scss' 6 | 7 | const SeparatorOption: FC = (): JSX.Element => ( 8 |
9 | ) 10 | 11 | export default SeparatorOption 12 | -------------------------------------------------------------------------------- /webapp/src/widgets/menuWrapper.scss: -------------------------------------------------------------------------------- 1 | .MenuWrapper { 2 | position: relative; 3 | cursor: default; 4 | 5 | &.disabled { 6 | cursor: default; 7 | } 8 | 9 | &.override.menuOpened { 10 | display: block; 11 | } 12 | 13 | *:first-child { 14 | /* stylelint-disable property-no-vendor-prefix*/ 15 | -webkit-user-select: text; /* Chrome all / Safari all */ 16 | -moz-user-select: text; /* Firefox all */ 17 | -ms-user-select: text; /* IE 10+ */ 18 | user-select: text; 19 | /* stylelint-enable property-no-vendor-prefix*/ 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /webapp/src/widgets/propertyMenu.scss: -------------------------------------------------------------------------------- 1 | .PropertyMenu { 2 | &.menu-textbox { 3 | font-weight: 400; 4 | padding: 2px 10px; 5 | cursor: text; 6 | touch-action: none; 7 | border: solid 1px #909090; 8 | border-radius: 3px; 9 | margin: 5px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /webapp/static/addDescription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/addDescription.png -------------------------------------------------------------------------------- /webapp/static/addProperty.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/addProperty.gif -------------------------------------------------------------------------------- /webapp/static/app-bar-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/app-bar-icon.png -------------------------------------------------------------------------------- /webapp/static/boards-screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/boards-screenshots.png -------------------------------------------------------------------------------- /webapp/static/boards-welcome-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/boards-welcome-small.png -------------------------------------------------------------------------------- /webapp/static/boards-welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/boards-welcome.png -------------------------------------------------------------------------------- /webapp/static/changeViews.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/changeViews.gif -------------------------------------------------------------------------------- /webapp/static/comment.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/comment.gif -------------------------------------------------------------------------------- /webapp/static/copyLink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/copyLink.gif -------------------------------------------------------------------------------- /webapp/static/emoji_spirit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/emoji_spirit.png -------------------------------------------------------------------------------- /webapp/static/onboardingBg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/onboardingBg.jpg -------------------------------------------------------------------------------- /webapp/static/share.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/share.gif -------------------------------------------------------------------------------- /webapp/static/upgrade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/webapp/static/upgrade.png -------------------------------------------------------------------------------- /webapp/webpack.prod.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 | // See LICENSE.txt for license information. 3 | const merge = require('webpack-merge'); 4 | const TerserPlugin = require('terser-webpack-plugin'); 5 | 6 | const makeCommonConfig = require('./webpack.common.js'); 7 | 8 | const commonConfig = makeCommonConfig(); 9 | 10 | const config = merge.merge(commonConfig, { 11 | mode: 'production', 12 | optimization: { 13 | minimize: true, 14 | minimizer: [new TerserPlugin({extractComments: false})], 15 | }, 16 | }); 17 | 18 | module.exports = [ 19 | merge.merge(config, { 20 | }), 21 | ]; 22 | -------------------------------------------------------------------------------- /website/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org/ 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | charset = utf-8 10 | 11 | [*.{md,css,html}] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | [*.toml] 16 | indent_style = space 17 | indent_size = 2 18 | 19 | [*.go] 20 | indent_style = tab 21 | 22 | [Makefile,*.mk] 23 | indent_style = tab 24 | 25 | [*.md] 26 | trim_trailing_whitespace = false 27 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # build artifacts 2 | dist 3 | 4 | # os artifacts 5 | *.swp 6 | .DS_Store 7 | 8 | # IDE artifacts 9 | .idea/ 10 | -------------------------------------------------------------------------------- /website/Makefile: -------------------------------------------------------------------------------- 1 | 2 | BASE_URL?=https://www.focalboard.com 3 | 4 | .PHONY: dist 5 | dist: 6 | rm -rf ./dist 7 | hugo -s site --destination ../dist/html -b$(BASE_URL) 8 | 9 | .PHONY: run 10 | run: 11 | hugo server --buildDrafts --disableFastRender -F -s site 12 | -------------------------------------------------------------------------------- /website/site/.hugo_build.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/.hugo_build.lock -------------------------------------------------------------------------------- /website/site/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | -------------------------------------------------------------------------------- /website/site/content/blog/2021-1-7-hello.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | slug: hello 4 | date: 2021-01-07 5 | categories: 6 | - "general" 7 | author: Chen Lim 8 | github: chenilim 9 | community: chen-i.lim 10 | --- 11 | 12 | > "I long to accomplish a great and noble task, but it is my chief duty to accomplish small tasks as if they were great and noble." 13 | > -- Helen Keller 14 | -------------------------------------------------------------------------------- /website/site/content/docs/personal-edition/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Personal Edition" 3 | date: "2020-12-15T12:01:23-04:00" 4 | section: "docs" 5 | weight: 1 6 | --- 7 | 8 | If you are new to Focalboard, [Personal Desktop](desktop) is the fastest way to try it out. 9 | 10 | To use it with your team, use [Mattermost Boards](../mattermost). 11 | You can import boards from Personal Desktop to Mattermost Boards. 12 | 13 | You can also set up the standalone Development or Personal Server on [Ubuntu](ubuntu) or with [Docker](docker). 14 | -------------------------------------------------------------------------------- /website/site/content/feedback/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "We love your feedback!" 3 | date: "2021-03-03T12:01:23-04:00" 4 | section: "feedback" 5 | weight: 1 6 | --- 7 | 8 | Please contact us via one of the following: 9 | * [File a GitHub issue](https://github.com/mattermost/focalboard/issues) for bugs or feature ideas 10 | * [Start a GitHub discussion](https://github.com/mattermost/focalboard/discussions) 11 | 12 | Focalboard is an open source project that is in early access. Help shape its future by sharing what you'd like to see with the community. 13 | 14 | Thank you for your input! 15 | -------------------------------------------------------------------------------- /website/site/content/fwlink/doc-boards.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page Moved 5 | 8 | 9 | 10 | This page has moved. Click here to go to the new page. 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/site/content/fwlink/plugin-setup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page Moved 5 | 8 | 9 | 10 | This page has moved. Click here to go to the new page. 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/site/content/fwlink/setup-536.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page Moved 5 | 8 | 9 | 10 | This page has moved. Click here to go to the new page. 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/site/content/fwlink/websocket-connect-error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Page Moved 5 | 8 | 9 | 10 | This page has moved. Click here to go to the new page. 11 | 12 | 13 | -------------------------------------------------------------------------------- /website/site/content/guide/user/add view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/add view.png -------------------------------------------------------------------------------- /website/site/content/guide/user/all tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/all tasks.png -------------------------------------------------------------------------------- /website/site/content/guide/user/board sidebar menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/board sidebar menu.png -------------------------------------------------------------------------------- /website/site/content/guide/user/by status properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/by status properties.png -------------------------------------------------------------------------------- /website/site/content/guide/user/by status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/by status.png -------------------------------------------------------------------------------- /website/site/content/guide/user/settings menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/settings menu.png -------------------------------------------------------------------------------- /website/site/content/guide/user/share board menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/share board menu.png -------------------------------------------------------------------------------- /website/site/content/guide/user/share board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/share board.png -------------------------------------------------------------------------------- /website/site/content/guide/user/table header menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/content/guide/user/table header menu.png -------------------------------------------------------------------------------- /website/site/content/guide/websocket-errors/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Troubleshooting: Websocket errors" 3 | date: "2021-06-14T12:01:23-04:00" 4 | section: "guide" 5 | weight: 4 6 | --- 7 | 8 | If the websocket persistently fails to connect to the server, check that the web proxy is configured correctly: 9 | * [If running Focalboard with Mattermost](/download/mattermost/) 10 | * [If running Focalboard Personal Server](/download/personal-edition/ubuntu/#configure-nginx) 11 | -------------------------------------------------------------------------------- /website/site/layouts/404.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /website/site/layouts/_default/_markup/render-link.html: -------------------------------------------------------------------------------- 1 | {{ htmlUnescape .Text }} -------------------------------------------------------------------------------- /website/site/layouts/blog/li.html: -------------------------------------------------------------------------------- 1 |
  • 2 |

    - {{ .Title}}
    3 | posted on {{ .Date.Format "January 2, 2006" }}

    4 |
  • 5 | -------------------------------------------------------------------------------- /website/site/layouts/partials/blogauthor.html: -------------------------------------------------------------------------------- 1 | {{ .name }} 2 | - 3 | 4 | @{{ .community }} 5 | 6 | on 7 | 8 | community.mattermost.com 9 | 10 | and 11 | 12 | @{{ .github }} 13 | 14 | on GitHub 15 | -------------------------------------------------------------------------------- /website/site/layouts/partials/hanchor.html: -------------------------------------------------------------------------------- 1 | {{ . | replaceRE "()" `${1} 
    ${3}` | safeHTML }} 2 | -------------------------------------------------------------------------------- /website/site/layouts/partials/mailinglist.html: -------------------------------------------------------------------------------- 1 | {{ if .Site.Params.mailinglist.enable }} 2 |
    3 | 4 |
    5 | {{ end }} 6 | -------------------------------------------------------------------------------- /website/site/layouts/partials/notification.html: -------------------------------------------------------------------------------- 1 | {{ if .Site.Params.notification.enable }} 2 | 12 | 13 | {{ end }} 14 | -------------------------------------------------------------------------------- /website/site/layouts/partials/page-edit.html: -------------------------------------------------------------------------------- 1 | {{ if .File }} 2 | 7 | Edit on GitHub 8 | 9 | {{ end }} 10 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/baseurl.html: -------------------------------------------------------------------------------- 1 | {{ .Page.Site.BaseURL }} 2 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/bignumber.html: -------------------------------------------------------------------------------- 1 |
    2 |
    {{ .Get "number" }}
    3 |
    4 |
    5 |

    {{ .Get "title" | markdownify }}

    6 |
    7 |
    8 | {{ .Get "content" | markdownify }} 9 |
    10 |
    11 |
    12 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/blogurl.html: -------------------------------------------------------------------------------- 1 | {{ .Page.Site.BaseURL }}blog 2 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/content.html: -------------------------------------------------------------------------------- 1 | {{ .Get 0 | readFile | markdownify }} 2 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/md.html: -------------------------------------------------------------------------------- 1 | {{ .Inner }} 2 | -------------------------------------------------------------------------------- /website/site/layouts/shortcodes/note.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /website/site/static/css/code.css: -------------------------------------------------------------------------------- 1 | code { 2 | padding: .2rem; 3 | } 4 | -------------------------------------------------------------------------------- /website/site/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /website/site/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /website/site/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /website/site/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /website/site/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /website/site/static/img/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/site/static/img/bgroundedcenter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/site/static/img/bgroundedleft.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/site/static/img/bgroundedright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/site/static/img/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/site/static/img/download-icon.svg: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /website/site/static/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/favicon-16x16.png -------------------------------------------------------------------------------- /website/site/static/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/favicon-32x32.png -------------------------------------------------------------------------------- /website/site/static/img/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/hero.jpg -------------------------------------------------------------------------------- /website/site/static/img/mentioned/newstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/mentioned/newstack.png -------------------------------------------------------------------------------- /website/site/static/img/mentioned/producthunt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/mentioned/producthunt.png -------------------------------------------------------------------------------- /website/site/static/img/mentioned/techrepublic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/mentioned/techrepublic.png -------------------------------------------------------------------------------- /website/site/static/img/mentioned/venturebeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/mentioned/venturebeat.png -------------------------------------------------------------------------------- /website/site/static/img/mentioned/ycombinator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/mentioned/ycombinator.png -------------------------------------------------------------------------------- /website/site/static/img/roadmap/analytics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/roadmap/analytics.png -------------------------------------------------------------------------------- /website/site/static/img/roadmap/card-dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/roadmap/card-dependencies.png -------------------------------------------------------------------------------- /website/site/static/img/roadmap/standard-properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/roadmap/standard-properties.png -------------------------------------------------------------------------------- /website/site/static/img/tabs/boards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/tabs/boards.png -------------------------------------------------------------------------------- /website/site/static/img/templates/company-goals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/company-goals.png -------------------------------------------------------------------------------- /website/site/static/img/templates/content-calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/content-calendar.png -------------------------------------------------------------------------------- /website/site/static/img/templates/meeting-agenda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/meeting-agenda.png -------------------------------------------------------------------------------- /website/site/static/img/templates/project-tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/project-tasks.png -------------------------------------------------------------------------------- /website/site/static/img/templates/roadmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/roadmap.png -------------------------------------------------------------------------------- /website/site/static/img/templates/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/templates/welcome.png -------------------------------------------------------------------------------- /website/site/static/img/use-icon.svg: -------------------------------------------------------------------------------- 1 | 7 | 15 | -------------------------------------------------------------------------------- /website/site/static/img/views/boardview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/views/boardview.png -------------------------------------------------------------------------------- /website/site/static/img/views/calendarview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/views/calendarview.png -------------------------------------------------------------------------------- /website/site/static/img/views/galleryview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/views/galleryview.png -------------------------------------------------------------------------------- /website/site/static/img/views/listview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/img/views/listview.png -------------------------------------------------------------------------------- /website/site/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Disallow: /cgi-bin/ 3 | Disallow: /&utm_source 4 | Disallow: /&utm_medium 5 | Disallow: /&utm_campaign 6 | Disallow: /?utm_ 7 | 8 | Sitemap: https://www.focalboard.com/sitemap.xml 9 | -------------------------------------------------------------------------------- /website/site/static/video/accelerate1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/video/accelerate1.mp4 -------------------------------------------------------------------------------- /website/site/static/video/comment-animation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/website/site/static/video/comment-animation.mp4 -------------------------------------------------------------------------------- /website/site/themes/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | -------------------------------------------------------------------------------- /website/site/themes/content/contribute/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contribute" 3 | date: "2017-08-19T12:01:23-04:00" 4 | --- 5 | 6 | # heading 7 | 8 | text! 9 | -------------------------------------------------------------------------------- /website/site/themes/layouts/404.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /website/site/themes/layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ partial "head.html" .}} 10 | 11 | 12 | {{ partial "nav.html" .}} 13 | {{ .Content }} 14 | 15 | 16 | -------------------------------------------------------------------------------- /website/site/themes/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ .Content }} 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/site/themes/layouts/partials/nav2.html: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /win-wpf/.gitignore: -------------------------------------------------------------------------------- 1 | packages 2 | obj 3 | msix 4 | temp 5 | dist 6 | *.msix 7 | *.suo 8 | *.csproj.user 9 | -------------------------------------------------------------------------------- /win-wpf/Focalboard/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /win-wpf/Focalboard/focalboard.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/win-wpf/Focalboard/focalboard.ico -------------------------------------------------------------------------------- /win-wpf/Focalboard/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /win-wpf/art/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/win-wpf/art/StoreLogo.png -------------------------------------------------------------------------------- /win-wpf/art/icon150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/win-wpf/art/icon150.png -------------------------------------------------------------------------------- /win-wpf/art/icon44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattermost-community/focalboard/de5e5cc4141f14f69bf0e5666383997b81f851d6/win-wpf/art/icon44.png -------------------------------------------------------------------------------- /win-wpf/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | WHERE msbuild.exe > nul 2>&1 4 | IF %ERRORLEVEL% NEQ 0 set PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin 5 | 6 | WHERE msbuild.exe > nul 2>&1 7 | IF %ERRORLEVEL% NEQ 0 set PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin 8 | 9 | WHERE msbuild.exe > nul 10 | IF %ERRORLEVEL% NEQ 0 echo msbuild.exe not found; exit /b 1 11 | 12 | echo Building... 13 | 14 | msbuild.exe Focalboard.sln /t:Rebuild /p:Configuration=Release /p:Platform="x64" /p:DebugSymbols=false /p:DebugType=None 15 | -------------------------------------------------------------------------------- /win-wpf/package-zip.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if exist dist\focalboard-win.zip del /q dist\focalboard-win.zip 4 | if not exist dist mkdir dist 5 | 6 | if exist temp del /s /f /q temp 7 | rmdir /s /q temp 8 | if not exist temp mkdir temp 9 | xcopy /e /i /y Focalboard\bin\x64\Release temp 10 | copy ..\build\MIT-COMPILED-LICENSE.md temp 11 | copy ..\NOTICE.txt temp 12 | copy ..\webapp\NOTICE.txt temp\webapp-NOTICE.txt 13 | 14 | echo --- Contents of temp --- 15 | dir /s /b temp 16 | echo --- 17 | 18 | powershell Compress-Archive -Path temp\* -DestinationPath dist\focalboard-win.zip 19 | -------------------------------------------------------------------------------- /win-wpf/package.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | WHERE makeappx.exe > nul 2>&1 4 | IF %ERRORLEVEL% NEQ 0 set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\App Certification Kit 5 | 6 | WHERE makeappx.exe > nul 7 | IF %ERRORLEVEL% NEQ 0 echo makeappx.exe not found; exit /b 1 8 | 9 | echo Packaging... 10 | 11 | rd /s /q msix 12 | mkdir msix 13 | xcopy /e /i /y Focalboard\bin\x64\Release msix 14 | mkdir msix\Assets 15 | copy art\StoreLogo.png msix\Assets 16 | copy art\icon150.png msix\Assets 17 | copy art\icon44.png msix\Assets 18 | copy AppxManifest.xml msix 19 | makeappx.exe pack /o /v /d msix /p Focalboard.msix 20 | --------------------------------------------------------------------------------