add method for filtering

This commit is contained in:
marlon-erler
2026-09-23 00:09:09 +02:00
parent 3458799a3b
commit 26c99085d2
61 changed files with 1703 additions and 1623 deletions
+1 -1
View File
@@ -1,4 +1,3 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
@@ -6,6 +5,7 @@ import {
createPropertyValueIndexState,
} from "../Components/propertyValueList";
import { FilteredList } from "../Components/filteredList";
import * as React from "../../react";
import { TaskCategoryBulkChangeViewModel } from "../../ViewModel/Utility/taskPropertyBulkChangeViewModel";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
+1 -1
View File
@@ -1,4 +1,3 @@
import * as React from "../../react";
import { BoardStatusGridPage } from "./boardStatusGridPage";
import { BoardKanbanPage } from "./boardKanbanPage";
import { ViewController } from "../viewController";
@@ -7,6 +6,7 @@ import { SearchModal } from "../Modals/searchModal";
import { BoardSettingsModal } from "../Modals/boardSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import { BoardViewToggleButton } from "../Components/boardViewToggleButton";
import * as React from "../../react";
import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
+1 -1
View File
@@ -1,4 +1,3 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
@@ -8,6 +7,7 @@ import {
createSortedPropertyValueState,
} from "../Components/propertyValueList";
import { FilteredList } from "../Components/filteredList";
import * as React from "../../react";
import {
TaskCategoryBulkChangeViewModel,
TaskStatusBulkChangeViewModel,
+1 -1
View File
@@ -1,10 +1,10 @@
import * as React from "../../react";
import "./calendarPage.css";
import { ViewController } from "../viewController";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import { PlaceholderView } from "../Components/placeholderView";
import { MonthGrid } from "../Components/monthGrid";
import * as React from "../../react";
import CalendarPageViewModel from "../../ViewModel/Pages/calendarPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+1 -1
View File
@@ -1,9 +1,9 @@
import * as React from "../../react";
import "./messagePage.css";
import { ViewController } from "../viewController";
import { MessageFilterModal } from "../Modals/messageFilterModal";
import { ReplyPreview } from "../Components/replyPreview";
import { ChatMessage } from "../Components/chatMessage";
import * as React from "../../react";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "../../react";
import { DeletableListItem } from "../Components/deletableListItem";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { ColorPicker } from "../Components/colorPicker";
import * as React from "../../react";
import SettingsPageViewModel from "../../ViewModel/Pages/settingsPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+3 -3
View File
@@ -1,9 +1,9 @@
import * as React from "../../react";
import "./taskPage.css";
import { BoardPage } from "./boardPage";
import { ViewController } from "../viewController";
import { PlaceholderView } from "../Components/placeholderView";
import { BoardViewModelToEntry } from "../Components/boardEntry";
import * as React from "../../react";
import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
@@ -62,7 +62,7 @@ export function TaskPage(
<div class="flex-row width-input">
<input
class="no-outline"
bind:value={taskPageViewModel.newBoardNameInput}
bind:value={taskPageViewModel.boardQuery}
on:enter={taskPageViewModel.createBoard}
placeholder={
coreViewModel.translations.chatPage.task
@@ -89,7 +89,7 @@ export function TaskPage(
class="grid gap"
style="grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr))"
children:append={[
taskPageViewModel.boardViewModels,
taskPageViewModel.boardMatches,
BoardViewModelToEntry,
]}
></div>
+1 -1
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import * as React from "../../react";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
export function BoardEntry(boardViewModel: BoardViewModel) {
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { RibbonButton } from "./ribbonButton";
import * as React from "../../react";
import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "../../react";
import { MessageReactionButtonRow } from "./messageReactionButtonRow";
import { InlineReply } from "./inlineReply";
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessageStatuses } from "../../Model/Chat/chatModel";
+1 -1
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { RibbonButton } from "./ribbonButton";
import * as React from "../../react";
import ChatViewModel, {
ChatPageTypes,
} from "../../ViewModel/Chat/chatViewModel";
+1 -1
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import * as React from "../../react";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
export function InlineReply(chatMessageViewModel: ChatMessageViewModel) {
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { MessageReactionButton } from "./messageReactionButton";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
+1 -1
View File
@@ -1,6 +1,6 @@
import * as React from "../../react";
import "./monthGrid.css";
import { ViewController } from "../viewController";
import * as React from "../../react";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { localeCompare } from "../../Model/Utility/utility";
+1 -1
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { OptionButton } from "./optionButton";
import * as React from "../../react";
export function OptionButtonList<T>(
options: React.ListState<[string, T]>,
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { ColorPicker } from "../Components/colorPicker";
import * as React from "../../react";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "../../react";
import { MessageReactionEntry } from "../Components/messageReactionEntry";
import { MessageReactionButtonRow } from "../Components/messageReactionButtonRow";
import { InfoTile } from "../Components/infoTile";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
+1 -1
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import { DeletableListItem } from "../Components/deletableListItem";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
+148 -142
View File
@@ -1,6 +1,6 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import { StringToTextSpan } from "../Components/textSpan";
import * as React from "../../react";
import FileTransferViewModel, {
FileTransferModals,
FileTransferOption,
@@ -758,7 +758,9 @@ function ExportModal(
</span>
<input
bind:value={fileTransferViewModel.exportKey}
on:enter={fileTransferViewModel.downloadFile}
on:enter={
fileTransferViewModel.downloadFile
}
type="password"
></input>
</div>
@@ -777,36 +779,38 @@ function ExportModal(
bind:value={
fileTransferViewModel.exportKeyConfirmation
}
on:enter={fileTransferViewModel.downloadFile}
type="password"
></input>
</div>
</label>
</div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showExportSelectionModal
}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.downloadFile}
toggle:disabled={fileTransferViewModel.cannotExport}
>
{
coreViewModel.translations.dataTransferModal
.downloadFileButton
}
<span class="icon">download</span>
</button>
</div>
</div>
</div>
on:enter={
fileTransferViewModel.downloadFile
}
type="password"
></input>
</div>
</label>
</div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showExportSelectionModal
}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.downloadFile}
toggle:disabled={fileTransferViewModel.cannotExport}
>
{
coreViewModel.translations.dataTransferModal
.downloadFileButton
}
<span class="icon">download</span>
</button>
</div>
</div>
</div>
);
}
@@ -815,57 +819,57 @@ function ImportModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
FileTransferModals.ImportSelection,
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
FileTransferModals.ImportSelection,
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.importHeadline
}
</h2>
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.importHeadline
}
</h2>
<div class="flex-column gap content-margin-bottom">
<input
id="file-transfer-input"
type="file"
on:change={
fileTransferViewModel.updateImportSelection
}
></input>
</div>
</main>
<div class="flex-column gap content-margin-bottom">
<input
id="file-transfer-input"
type="file"
on:change={
fileTransferViewModel.updateImportSelection
}
></input>
</div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showDirectionSelectionModal
}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.importFile}
toggle:disabled={fileTransferViewModel.cannotImport}
>
{
coreViewModel.translations.dataTransferModal
.importFileButton
}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showDirectionSelectionModal
}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.importFile}
toggle:disabled={fileTransferViewModel.cannotImport}
>
{
coreViewModel.translations.dataTransferModal
.importFileButton
}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
}
@@ -874,74 +878,76 @@ function ImportDecryptionDataModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
FileTransferModals.ImportDecryptData,
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
FileTransferModals.ImportDecryptData,
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.importHeadline
}
</h2>
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.importHeadline
}
</h2>
<div class="flex-column gap content-margin-bottom">
<label class="tile">
<span class="icon">key</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal.exportKey
}
</span>
<input
bind:value={fileTransferViewModel.importKey}
on:enter={fileTransferViewModel.decryptImport}
type="password"
></input>
</div>
</label>
</div>
<div class="flex-column gap content-margin-bottom">
<label class="tile">
<span class="icon">key</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal.exportKey
}
</span>
<input
bind:value={fileTransferViewModel.importKey}
on:enter={
fileTransferViewModel.decryptImport
}
type="password"
></input>
</div>
</label>
</div>
<p
class="error"
toggle:hidden={fileTransferViewModel.isImportKeyCorrect}
>
{
coreViewModel.translations.dataTransferModal
.incorrectPassphraseError
}
</p>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={fileTransferViewModel.showImportModal}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.decryptImport}
toggle:disabled={
fileTransferViewModel.importDecryptSuccessful
}
>
{
coreViewModel.translations.dataTransferModal
.decryptImportButton
}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
<p
class="error"
toggle:hidden={fileTransferViewModel.isImportKeyCorrect}
>
{
coreViewModel.translations.dataTransferModal
.incorrectPassphraseError
}
</p>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={fileTransferViewModel.showImportModal}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.decryptImport}
toggle:disabled={
fileTransferViewModel.importDecryptSuccessful
}
>
{
coreViewModel.translations.dataTransferModal
.decryptImportButton
}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
}
+1 -1
View File
@@ -1,6 +1,6 @@
import * as React from "../../react";
import { ViewController } from "../viewController";
import { MessageReactionFilterButton } from "../Components/messageReactionFilterButton";
import * as React from "../../react";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
+62 -44
View File
@@ -1,7 +1,7 @@
import { v4 } from "uuid";
import * as React from "../../react";
import { ViewController } from "../viewController";
import { StringToOption } from "../Components/option";
import * as React from "../../react";
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
@@ -29,8 +29,8 @@ export function SearchModal<T>(
<h2>{headline}</h2>
<div class="flex-row">
<input
id="focused"
style="max-width: unset"
id="focused"
style="max-width: unset"
placeholder={
coreViewModel.translations.general.searchLabel
}
@@ -70,55 +70,73 @@ export function SearchModal<T>(
</button>
</div>
<div
toggle:hidden={searchViewModel.hasNoSuggestions}>
<hr></hr>
<h3>{coreViewModel.translations.general.searchSuggestionsLabel}</h3>
<div
class="flex-column gap"
children:append={[
searchViewModel.suggestions,
(suggestion: string) => SuggestionView(suggestion, searchViewModel, coreViewModel),
]}
></div>
</div>
</main>
<button on:click={close}>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
</div>
</div>
<div toggle:hidden={searchViewModel.hasNoSuggestions}>
<hr></hr>
<h3>
{
coreViewModel.translations.general
.searchSuggestionsLabel
}
</h3>
<div
class="flex-column gap"
children:append={[
searchViewModel.suggestions,
(suggestion: string) =>
SuggestionView(
suggestion,
searchViewModel,
coreViewModel,
),
]}
></div>
</div>
</main>
<button on:click={close}>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
</div>
</div>
);
}
function SuggestionView<T>(suggestion: string, searchViewModel: SearchViewModel<T>, coreViewModel: CoreViewModel) {
const isApplied = React.createProxyState([searchViewModel.appliedQuery], ()=>searchViewModel.appliedQuery.value == suggestion);
function SuggestionView<T>(
suggestion: string,
searchViewModel: SearchViewModel<T>,
coreViewModel: CoreViewModel,
) {
const isApplied = React.createProxyState(
[searchViewModel.appliedQuery],
() => searchViewModel.appliedQuery.value == suggestion,
);
function deleteSuggestion() {
searchViewModel.deleteSuggestion(suggestion);
searchViewModel.deleteSuggestion(suggestion);
}
function applySuggestion() {
searchViewModel.search(suggestion);
searchViewModel.search(suggestion);
}
return <div class="flex-row surface align-center">
<span class="width-100 flex-1 padding-h">{suggestion}</span>
<button
class="danger"
aria-label={coreViewModel.translations.general.deleteButton}
on:click={deleteSuggestion}
>
<span class="icon">delete</span>
</button>
<button
class="primary"
aria-label={coreViewModel.translations.general.applyButton}
on:click={applySuggestion}
toggle:disabled={isApplied}
>
<span class="icon">check</span>
</button>
</div>
return (
<div class="flex-row surface align-center">
<span class="width-100 flex-1 padding-h">{suggestion}</span>
<button
class="danger"
aria-label={coreViewModel.translations.general.deleteButton}
on:click={deleteSuggestion}
>
<span class="icon">delete</span>
</button>
<button
class="primary"
aria-label={coreViewModel.translations.general.applyButton}
on:click={applySuggestion}
toggle:disabled={isApplied}
>
<span class="icon">check</span>
</button>
</div>
);
}
+1 -1
View File
@@ -1,10 +1,10 @@
import * as React from "../../react";
import { SplitModal } from "./splitModal";
import { languageNames } from "../translations";
import { PlaceholderView } from "../Components/placeholderView";
import { OptionButtonList } from "../Components/optionButtonList";
import { NavigationButton } from "../Components/navigationButton";
import { InfoTile } from "../Components/infoTile";
import * as React from "../../react";
import SettingsViewModel, {
SettingsModalPages,
} from "../../ViewModel/Global/settingsViewModel";
+2 -2
View File
@@ -1,5 +1,5 @@
import * as React from "../../react";
import "./splitModal.css";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function SplitModal<T>(
@@ -10,7 +10,7 @@ export function SplitModal<T>(
navigationState?: React.State<T | undefined>,
) {
function closePage() {
if (!navigationState) return;
if (!navigationState) return;
navigationState.value = undefined;
}
+1 -1
View File
@@ -1,7 +1,7 @@
import * as React from "../../react";
import { SplitModal } from "./splitModal";
import { DirectoryItemList } from "../Components/directoryItemList";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import * as React from "../../react";
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
+247 -242
View File
@@ -1,5 +1,4 @@
import { v4 } from "uuid";
import * as React from "../../react";
import {
Entry,
Option,
@@ -7,6 +6,7 @@ import {
VersionIdToOption,
} from "../Components/option";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import * as React from "../../react";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
@@ -18,264 +18,269 @@ export function TaskSettingsModal(
const statusSuggestionId = v4();
const BoardOptionConverter: React.StateItemConverter<Entry> = (
entry: Entry,
entry: Entry,
) => {
const isSelected = entry[0] == taskViewModel.task.boardId;
return Option(entry[1], entry[0], isSelected);
const isSelected = entry[0] == taskViewModel.task.boardId;
return Option(entry[1], entry[0], isSelected);
};
return (
<div class="modal task-settings" open toggle:full-description={taskViewModel.isPresentingFullScreenDescription}>
<div>
<main id="standard-main">
<h2>
{
coreViewModel.translations.chatPage.task
.taskSettingsHeadline
}
</h2>
<div
class="modal task-settings"
open
toggle:full-description={
taskViewModel.isPresentingFullScreenDescription
}
>
<div>
<main id="standard-main">
<h2>
{
coreViewModel.translations.chatPage.task
.taskSettingsHeadline
}
</h2>
<div class="column-wrapper">
<div class="flex-column">
<label class="tile flex-no">
<span class="icon">label</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskNameLabel
}
</span>
<input
bind:value={taskViewModel.name}
></input>
</div>
</label>
<div class="column-wrapper">
<div class="flex-column">
<label class="tile flex-no">
<span class="icon">label</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskNameLabel
}
</span>
<input
bind:value={taskViewModel.name}
></input>
</div>
</label>
<label class="tile flex-no">
<span class="icon">category</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskBoardLabel
}
</span>
<select
bind:value={taskViewModel.boardId}
children:append={[
taskViewModel.chatViewModel
.taskBoardSuggestions,
BoardOptionConverter,
]}
></select>
<span class="icon">arrow_drop_down</span>
</div>
</label>
<label class="tile flex-no">
<span class="icon">category</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskBoardLabel
}
</span>
<select
bind:value={taskViewModel.boardId}
children:append={[
taskViewModel.chatViewModel
.taskBoardSuggestions,
BoardOptionConverter,
]}
></select>
<span class="icon">arrow_drop_down</span>
</div>
</label>
<label class="tile flex-no">
<span class="icon">description</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskDescriptionLabel
}
</span>
<textarea
rows="10"
bind:value={taskViewModel.description}
></textarea>
</div>
</label>
<div class="flex-row justify-end">
<button
class="width-50"
on:click={taskViewModel.openFullscreenDecription}
>
{
coreViewModel.translations.general.fullscreenButton
}
<label class="tile flex-no">
<span class="icon">description</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskDescriptionLabel
}
</span>
<textarea
rows="10"
bind:value={taskViewModel.description}
></textarea>
</div>
</label>
<div class="flex-row justify-end">
<button
class="width-50"
on:click={
taskViewModel.openFullscreenDecription
}
>
{
coreViewModel.translations.general
.fullscreenButton
}
<span class="icon">fullscreen</span>
</button>
</div>
</div>
<span class="icon">fullscreen</span>
</button>
</div>
</div>
<hr class="mobile-only"></hr>
<hr class="mobile-only"></hr>
<div class="flex-column">
<label class="tile flex-no">
<span class="icon">category</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskCategoryLabel
}
</span>
<input
bind:value={taskViewModel.category}
list={categorySuggestionId}
></input>
</div>
</label>
<datalist
hidden
id={categorySuggestionId}
children:append={[
taskViewModel.containingViewModel.taskCategorySuggestions,
StringToOption,
]}
></datalist>
<div class="flex-column">
<label class="tile flex-no">
<span class="icon">category</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskCategoryLabel
}
</span>
<input
bind:value={taskViewModel.category}
list={categorySuggestionId}
></input>
</div>
</label>
<datalist
hidden
id={categorySuggestionId}
children:append={[
taskViewModel.containingViewModel
.taskCategorySuggestions,
StringToOption,
]}
></datalist>
<label class="tile flex-no">
<span class="icon">clock_loader_40</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskStatusLabel
}
</span>
<input
bind:value={taskViewModel.status}
list={statusSuggestionId}
></input>
</div>
</label>
<datalist
hidden
id={statusSuggestionId}
children:append={[
taskViewModel.containingViewModel.taskStatusSuggestions,
StringToOption,
]}
></datalist>
<label class="tile flex-no">
<span class="icon">clock_loader_40</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskStatusLabel
}
</span>
<input
bind:value={taskViewModel.status}
list={statusSuggestionId}
></input>
</div>
</label>
<datalist
hidden
id={statusSuggestionId}
children:append={[
taskViewModel.containingViewModel
.taskStatusSuggestions,
StringToOption,
]}
></datalist>
<label class="tile flex-no">
<span class="icon">priority_high</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskPriorityLabel
}
</span>
<input
type="number"
bind:value={taskViewModel.priority}
></input>
</div>
</label>
<label class="tile flex-no">
<span class="icon">priority_high</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskPriorityLabel
}
</span>
<input
type="number"
bind:value={taskViewModel.priority}
></input>
</div>
</label>
<hr></hr>
<hr></hr>
<label class="tile flex-no">
<span class="icon">calendar_month</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskDateLabel
}
</span>
<input
type="date"
bind:value={taskViewModel.date}
></input>
</div>
</label>
<label class="tile flex-no">
<span class="icon">calendar_month</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskDateLabel
}
</span>
<input
type="date"
bind:value={taskViewModel.date}
></input>
</div>
</label>
<label class="tile flex-no">
<span class="icon">schedule</span>
<div>
<span>
{
coreViewModel.translations.chatPage.task
.taskTimeLabel
}
</span>
<input
type="time"
bind:value={taskViewModel.time}
></input>
</div>
</label>
</div>
</div>
<label class="tile flex-no">
<span class="icon">schedule</span>
<div>
<span>
{
coreViewModel.translations.chatPage
.task.taskTimeLabel
}
</span>
<input
type="time"
bind:value={taskViewModel.time}
></input>
</div>
</label>
</div>
</div>
<hr></hr>
<hr></hr>
<label class="tile flex-no">
<span class="icon">history</span>
<div>
<span>
{
coreViewModel.translations.general
.fileVersionLabel
}
</span>
<select
bind:value={taskViewModel.selectedVersionId}
children:append={[
taskViewModel.versionIds,
VersionIdToOption,
]}
></select>
<span class="icon">arrow_drop_down</span>
</div>
</label>
<label class="tile flex-no">
<span class="icon">history</span>
<div>
<span>
{
coreViewModel.translations.general
.fileVersionLabel
}
</span>
<select
bind:value={taskViewModel.selectedVersionId}
children:append={[
taskViewModel.versionIds,
VersionIdToOption,
]}
></select>
<span class="icon">arrow_drop_down</span>
</div>
</label>
<hr></hr>
<hr></hr>
<div class="width-input">
{DangerousActionButton(
coreViewModel,
coreViewModel.translations.chatPage.task
.deleteTaskButton,
"delete_forever",
taskViewModel.deleteTask,
)}
</div>
</main>
<main id="fullscreen-main">
<textarea
style="height: 100%; width: 100%; max-width: unset"
bind:value={taskViewModel.description}
></textarea>
</main>
<div
class="flex-row width-100"
id="fullscreen-exit"
>
<button
class="flex"
on:click={taskViewModel.closeFullscreenDecription}
>
{coreViewModel.translations.general.exitButton}
<span class="icon">fullscreen_exit</span>
</button>
</div>
<div
class="flex-row width-100"
id="controls"
>
<button
class="flex"
on:click={taskViewModel.closeAndDiscard}
>
{coreViewModel.translations.general.closeButton}
</button>
<button
class="flex primary"
on:click={taskViewModel.closeAndSave}
>
{coreViewModel.translations.general.saveButton}
<span class="icon">save</span>
</button>
</div>
</div>
</div>
);
<div class="width-input">
{DangerousActionButton(
coreViewModel,
coreViewModel.translations.chatPage.task
.deleteTaskButton,
"delete_forever",
taskViewModel.deleteTask,
)}
</div>
</main>
<main id="fullscreen-main">
<textarea
style="height: 100%; width: 100%; max-width: unset"
bind:value={taskViewModel.description}
></textarea>
</main>
<div class="flex-row width-100" id="fullscreen-exit">
<button
class="flex"
on:click={taskViewModel.closeFullscreenDecription}
>
{coreViewModel.translations.general.exitButton}
<span class="icon">fullscreen_exit</span>
</button>
</div>
<div class="flex-row width-100" id="controls">
<button
class="flex"
on:click={taskViewModel.closeAndDiscard}
>
{coreViewModel.translations.general.closeButton}
</button>
<button
class="flex primary"
on:click={taskViewModel.closeAndSave}
>
{coreViewModel.translations.general.saveButton}
<span class="icon">save</span>
</button>
</div>
</div>
</div>
);
}
+47 -46
View File
@@ -65,9 +65,9 @@ body[showing-chat] #chat-page-wrapper {
overflow: hidden;
}
@media (pointer: coarse) and (max-width: 480px){
@media (pointer: coarse) and (max-width: 480px) {
#chat-page > div > #main > div > .pane-wrapper > .pane {
flex-direction: column-reverse;
flex-direction: column-reverse;
}
}
@@ -78,13 +78,13 @@ body[showing-chat] #chat-page-wrapper {
@media (min-width: 1024px) {
#chat-page > div > #main > div > .pane-wrapper {
min-width: unset;
min-width: unset;
}
#chat-page > div > #main > div > .pane-wrapper.side {
width: 18rem;
min-width: 18rem;
max-width: 18rem;
width: 18rem;
min-width: 18rem;
max-width: 18rem;
}
}
@@ -114,21 +114,21 @@ body[showing-chat] #chat-page-wrapper {
#chat-page > div > #ribbon > span,
#chat-page
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
> span.ribbon {
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
> span.ribbon {
gap: var(--gap-between-tiles);
padding: var(--gap-between-tiles);
}
@media (pointer: coarse) and (max-width: 480px){
#chat-page > div > #ribbon #close-button {
order: 1;
}
@media (pointer: coarse) and (max-width: 480px) {
#chat-page > div > #ribbon #close-button {
order: 1;
}
}
#chat-page > div > #main > div > .pane-wrapper > .pane > .toolbar {
@@ -192,13 +192,13 @@ body[showing-chat] #chat-page-wrapper {
#chat-page > div > #ribbon button.ribbon-button,
#chat-page
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
button.ribbon-button {
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
button.ribbon-button {
min-width: calc(var(--control-height) - 2 * var(--gap-between-tiles));
width: calc(var(--control-height) - 2 * var(--gap-between-tiles));
max-width: calc(var(--control-height) - 2 * var(--gap-between-tiles));
@@ -211,14 +211,14 @@ button.ribbon-button {
#chat-page > div > #ribbon button > .icon,
#chat-page
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
button
> .icon {
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
button
> .icon {
font-size: 1.1rem;
}
@@ -244,13 +244,13 @@ button
}
#chat-page
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
:is(input, select, button) {
> div
> #main
> div
> .pane-wrapper
> .pane
> .toolbar
:is(input, select, button) {
height: 100%;
flex: 1;
}
@@ -262,18 +262,19 @@ button
@media (min-width: 640px) {
.modal.task-settings .column-wrapper {
display: flex;
flex-direction: row;
gap: var(--content-padding);
display: flex;
flex-direction: row;
gap: var(--content-padding);
}
.modal.task-settings .column-wrapper > .flex-column{
width: 100%;
flex: 1;
.modal.task-settings .column-wrapper > .flex-column {
width: 100%;
flex: 1;
}
}
.modal.task-settings:not([full-description]) :is(#fullscreen-exit, #fullscreen-main) {
.modal.task-settings:not([full-description])
:is(#fullscreen-exit, #fullscreen-main) {
display: none;
}
+44 -43
View File
@@ -1,4 +1,3 @@
import * as React from "../react";
import { ViewController } from "./viewController";
import "./homePage.css";
import { ChatViewToggleButton } from "./Components/chatViewToggleButton";
@@ -6,6 +5,7 @@ import { TaskPage } from "./ChatPages/taskPage";
import { SettingsPage } from "./ChatPages/settingsPage";
import { MessagePage } from "./ChatPages/messagePage";
import { CalendarPage } from "./ChatPages/calendarPage";
import * as React from "../react";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../ViewModel/Chat/chatViewModel";
@@ -73,8 +73,8 @@ export function ChatPage(
<div>
<div id="ribbon">
<button
class="ghost"
id="close-button"
class="ghost"
id="close-button"
aria-label={
coreViewModel.translations.chatPage
.closeChatAudioLabe
@@ -95,47 +95,48 @@ export function ChatPage(
toggle:hidden={
chatViewModel.connectionViewModel.isConnected
}
toggle:disabled={
chatViewModel.connectionViewModel.hasNoPreviousConnections
}
>
<span class="icon">signal_disconnected</span>
</button>
toggle:disabled={
chatViewModel.connectionViewModel
.hasNoPreviousConnections
}
>
<span class="icon">signal_disconnected</span>
</button>
<span class="marquee" children:set={marqueeContent}></span>
<span class="marquee" children:set={marqueeContent}></span>
<span class="navigation-buttons">
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.calendar,
"calendar_month",
ChatPageTypes.Calendar,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.tasks,
"task_alt",
ChatPageTypes.Tasks,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.messages,
"forum",
ChatPageTypes.Messages,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.settings,
"settings",
ChatPageTypes.Settings,
chatViewModel,
)}
</span>
</div>
<div
id="main"
children:set={ViewController.chatPages.state}
></div>
</div>
</article>
<span class="navigation-buttons">
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.calendar,
"calendar_month",
ChatPageTypes.Calendar,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.tasks,
"task_alt",
ChatPageTypes.Tasks,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.messages,
"forum",
ChatPageTypes.Messages,
chatViewModel,
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.settings,
"settings",
ChatPageTypes.Settings,
chatViewModel,
)}
</span>
</div>
<div
id="main"
children:set={ViewController.chatPages.state}
></div>
</div>
</article>
);
}
+1 -1
View File
@@ -1,6 +1,6 @@
import * as React from "../react";
import "./chatPage.css";
import { ChatPage } from "./chatPage";
import * as React from "../react";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
+1 -1
View File
@@ -1,8 +1,8 @@
import * as React from "../react";
import "./homePage.css";
import { StringToOption } from "./Components/option";
import { HomePageButton } from "./Components/homePageButton";
import { ChatViewModelToChatEntry } from "./Components/chatEntry";
import * as React from "../react";
import StorageViewModel from "../ViewModel/Global/storageViewModel";
import SettingsViewModel from "../ViewModel/Global/settingsViewModel";
import FileTransferViewModel from "../ViewModel/Global/fileTransferViewModel";
+536 -536
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@ class Tracker<T> {
class TrackerMap<T> {
trackers = new Map<string, Tracker<T>>();
private register = (key: string): Tracker<T>=> {
private register = (key: string): Tracker<T> => {
if (this.trackers.has(key)) {
return this.trackers.get(key)!;
}