prepare layout for object views

This commit is contained in:
marlon-erler
2024-07-11 18:54:56 +02:00
parent d13ea988fc
commit 0a20c7d1d9
8 changed files with 304 additions and 69 deletions
+138 -33
View File
@@ -975,7 +975,7 @@
serverAddress: "Server Address", serverAddress: "Server Address",
serverAddressPlaceholder: "wss://192.168.0.69:3000", serverAddressPlaceholder: "wss://192.168.0.69:3000",
connectToServer: "Connect", connectToServer: "Connect",
disconnect: "Disonnect", disconnect: "Disconnect",
mailbox: "Mailbox", mailbox: "Mailbox",
requestMailbox: "Enable", requestMailbox: "Enable",
deleteMailbox: "Disable", deleteMailbox: "Disable",
@@ -1009,6 +1009,10 @@
showObjects: "show objects", showObjects: "show objects",
createObject: "create object", createObject: "create object",
untitledObject: "Untitled Object", untitledObject: "Untitled Object",
viewAll: "All",
viewNotes: "Notes",
noObjects: "No objects",
noNotes: "No notes",
objectTitle: "Object title", objectTitle: "Object title",
objectTitlePlaceholder: "My object", objectTitlePlaceholder: "My object",
objectVersion: "Object version", objectVersion: "Object version",
@@ -1022,18 +1026,20 @@
es: { es: {
// general // general
set: "Guardar", set: "Guardar",
save: "Guardar",
back: "Atr\xE1s", back: "Atr\xE1s",
undoChanges: "Deshacer", undoChanges: "Deshacer",
close: "Cerrar", close: "Cerrar",
discard: "Descartar",
// overview // overview
overview: "Resumen", overview: "Resumen",
connection: "Conexion", connection: "Conexi\xF3n",
chats: "Chats", chats: "Chats",
yourName: "Tu nombre", yourName: "Tu nombre",
namePlaceholder: "Juan P\xE9rez", namePlaceholder: "Juan P\xE9rez",
encryptionUnavailableTitle: "Cifrado no disponible", encryptionUnavailableTitle: "Cifrado no disponible",
encryptionUnavailableMessage: "Obt\xE9n esta aplicaci\xF3n a traves de HTTPS o contin\xFAa sin cifrado", encryptionUnavailableMessage: "Obt\xE9n esta aplicaci\xF3n a traves de HTTPS o contin\xFAa sin cifrado",
serverAddress: "Direccion del servidor", serverAddress: "Direcci\xF3n del servidor",
serverAddressPlaceholder: "wss://192.168.0.69:3000", serverAddressPlaceholder: "wss://192.168.0.69:3000",
connectToServer: "Conectar", connectToServer: "Conectar",
disconnect: "Desconectar", disconnect: "Desconectar",
@@ -1044,33 +1050,48 @@
primaryChannel: "Canal principal", primaryChannel: "Canal principal",
primaryChannelPlaceholder: "mi-canal", primaryChannelPlaceholder: "mi-canal",
addChat: "A\xF1adir", addChat: "A\xF1adir",
// messages // chat
showChatOptions: "Mostrar opciones del chat", showChatOptions: "Mostrar opciones del chat",
configureChatTitle: "Configurar chat", configureChatTitle: "Configurar chat",
secondaryChannel: "Canal segundario", secondaryChannel: "Canal secundario",
secondaryChannelPlaceholder: "A\xF1adir canal segundario", secondaryChannelPlaceholder: "A\xF1adir canal secundario",
addSecondaryChannel: "A\xF1adir canal segundario", addSecondaryChannel: "A\xF1adir canal secundario",
removeSecondaryChannel: "Eliminar canal segundario", removeSecondaryChannel: "Eliminar canal secundario",
encryptionKey: "Clave de cifrado", encryptionKey: "Clave de cifrado",
encryptionKeyPlaceholder: "n10d2482dg283hg", encryptionKeyPlaceholder: "n10d2482dg283hg",
showKey: "Mostrar clave", showKey: "Mostrar clave",
clearObjects: "Eliminar todos los objetos",
clearChatMessages: "Eliminar todos los mensajes",
removeChat: "Eliminar chat", removeChat: "Eliminar chat",
clearChatMessages: "Eliminar todos mensajes",
noChatSelected: "Selecciona un chat",
messageInOutbox: "Pendiente", messageInOutbox: "Pendiente",
noChatSelected: "Selecciona un chat",
composerPlaceholder: "Escribe un mensaje...", composerPlaceholder: "Escribe un mensaje...",
sendMessage: "Enviar", sendMessage: "Enviar",
resendMessage: "Enviar de nuevo", // messages
resendMessage: "Reenviar mensaje",
decryptMessage: "Descifrar mensaje", decryptMessage: "Descifrar mensaje",
copyMessage: "Copiar mensaje", copyMessage: "Copiar mensaje",
deleteMessage: "Eliminar este mensaje" deleteMessage: "Eliminar este mensaje",
// objects
showObjects: "mostrar objetos",
createObject: "a\xF1adir nuevo objeto",
untitledObject: "Sin T\xEDtulo",
objectTitle: "T\xEDtulo",
objectTitlePlaceholder: "Mi objeto",
objectVersion: "Version del objeto",
noteContent: "Nota",
noteContentPlaceholder: "Toma nota...",
resendObjects: "Reenviar todos objetos",
deleteObject: "Eliminar objeto"
}, },
de: { de: {
// general // general
set: "OK", set: "OK",
save: "Sichern",
back: "Zur\xFCck", back: "Zur\xFCck",
undoChanges: "\xC4nderungen verwerfen", undoChanges: "\xC4nderungen verwerfen",
close: "Schlie\xDFen", close: "Schlie\xDFen",
discard: "Verwerfen",
// overview // overview
overview: "\xDCbersicht", overview: "\xDCbersicht",
connection: "Verbindung", connection: "Verbindung",
@@ -1090,7 +1111,7 @@
primaryChannel: "Hauptkanal", primaryChannel: "Hauptkanal",
primaryChannelPlaceholder: "mein-kanal", primaryChannelPlaceholder: "mein-kanal",
addChat: "Hinzuf\xFCgen", addChat: "Hinzuf\xFCgen",
// messages // chat
showChatOptions: "Chatoptionen einblenden", showChatOptions: "Chatoptionen einblenden",
configureChatTitle: "Chat konfigurieren", configureChatTitle: "Chat konfigurieren",
secondaryChannel: "Zweitkanal", secondaryChannel: "Zweitkanal",
@@ -1100,21 +1121,80 @@
encryptionKey: "Schl\xFCssel", encryptionKey: "Schl\xFCssel",
encryptionKeyPlaceholder: "n10d2482dg283hg", encryptionKeyPlaceholder: "n10d2482dg283hg",
showKey: "Schl\xFCssel anzeigen", showKey: "Schl\xFCssel anzeigen",
removeChat: "Chat l\xF6schen", clearObjects: "Alle Objekte l\xF6schen",
clearChatMessages: "Nachrichtenverlauf leeren", clearChatMessages: "Nachrichtenverlauf leeren",
noChatSelected: "Kein Chat ausgew\xE4hlt", removeChat: "Chat l\xF6schen",
messageInOutbox: "Ausstehend", messageInOutbox: "Ausstehend",
noChatSelected: "Kein Chat ausgew\xE4hlt",
composerPlaceholder: "Neue Nachricht...", composerPlaceholder: "Neue Nachricht...",
sendMessage: "Senden", sendMessage: "Senden",
// messages
resendMessage: "Erneut senden", resendMessage: "Erneut senden",
decryptMessage: "Nachricht entschl\xFCsseln", decryptMessage: "Nachricht entschl\xFCsseln",
copyMessage: "Nachricht kopieren", copyMessage: "Nachricht kopieren",
deleteMessage: "Nachricht l\xF6schen" deleteMessage: "Nachricht l\xF6schen",
// objects
showObjects: "Objekte anzeigen",
createObject: "Neues Objekt erstellen",
untitledObject: "Unbenannt",
objectTitle: "Titel",
objectTitlePlaceholder: "Mein Objekt",
objectVersion: "Version des Objekts",
noteContent: "Notiz",
noteContentPlaceholder: "Notiz eingeben...",
resendObjects: "Objekte erneut senden",
deleteObject: "Objekt l\xF6schen"
} }
}; };
var language = navigator.language.substring(0, 2); var language = navigator.language.substring(0, 2);
var translation = allTranslations[language] ?? allTranslations.en; var translation = allTranslations[language] ?? allTranslations.en;
// src/Views/Objects/allObjectsView.tsx
function AllObjectsView(chat, selectedObject, isShowingObjectModal) {
const objectConverter = (messageObject) => {
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return /* @__PURE__ */ createElement("button", { class: "tile", "on:click": select }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, messageObject.title), /* @__PURE__ */ createElement("span", { class: "secondary" }, messageObject.id)));
};
const content = createProxyState(
[chat.objects],
() => chat.objects.value.size == 0 ? /* @__PURE__ */ createElement("div", { class: "flex-column width-100 height-100 align-center justify-center secondary" }, translation.noObjects) : /* @__PURE__ */ createElement(
"div",
{
class: "grid gap padding",
style: "grid-template-columns: repeat(auto-fit, minmax(350px, 1fr))",
"children:prepend": [chat.objects, objectConverter]
}
)
);
return /* @__PURE__ */ createElement("div", { class: "width-100 height-100", "children:set": content });
}
// src/Views/Objects/noteObjectsView.tsx
function NoteObjectsView(chat, selectedObject, isShowingObjectModal) {
const objectConverter = (messageObject) => {
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return /* @__PURE__ */ createElement("button", { class: "tile", "on:click": select }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, messageObject.title), /* @__PURE__ */ createElement("span", { class: "secondary" }, messageObject.id)));
};
const content = createProxyState(
[chat.objects],
() => chat.objects.value.size == 0 ? /* @__PURE__ */ createElement("div", { class: "flex-column width-100 height-100 align-center justify-center secondary" }, translation.noNotes) : /* @__PURE__ */ createElement(
"div",
{
class: "grid gap padding",
style: "grid-template-columns: repeat(auto-fit, minmax(350px, 1fr))",
"children:prepend": [chat.objects, objectConverter]
}
)
);
return /* @__PURE__ */ createElement("div", { class: "width-100 height-100", "children:set": content });
}
// src/Views/Objects/objectDetailModal.tsx // src/Views/Objects/objectDetailModal.tsx
function ObjectDetailModal(chat, messageObject, isPresented) { function ObjectDetailModal(chat, messageObject, isPresented) {
const editingTitle = new State(messageObject.title); const editingTitle = new State(messageObject.title);
@@ -1165,6 +1245,7 @@
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented, "on:keydown": handleKeyDown }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, messageObject.title), /* @__PURE__ */ createElement("span", { class: "secondary" }, messageObject.id), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap" }, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "label"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.objectTitle), /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented, "on:keydown": handleKeyDown }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, messageObject.title), /* @__PURE__ */ createElement("span", { class: "secondary" }, messageObject.id), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap" }, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "label"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.objectTitle), /* @__PURE__ */ createElement(
"input", "input",
{ {
autofocus: true,
"bind:value": editingTitle, "bind:value": editingTitle,
placeholder: translation.objectTitlePlaceholder placeholder: translation.objectTitlePlaceholder
} }
@@ -1180,12 +1261,11 @@
))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("button", { class: "danger width-input", "on:click": deleteAndClose }, translation.deleteObject, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete")))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 danger", "on:click": closeModal }, translation.discard), /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 primary", "on:click": saveAndClose }, translation.save, /* @__PURE__ */ createElement("span", { class: "icon" }, "save"))))); ))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("button", { class: "danger width-input", "on:click": deleteAndClose }, translation.deleteObject, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete")))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 danger", "on:click": closeModal }, translation.discard), /* @__PURE__ */ createElement("button", { class: "flex-1 width-100 primary", "on:click": saveAndClose }, translation.save, /* @__PURE__ */ createElement("span", { class: "icon" }, "save")))));
} }
// src/Views/Objects/objectListEntry.tsx
function ObjectListEntry(messageObject, onclick) {
return /* @__PURE__ */ createElement("button", { class: "tile", "on:click": onclick }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, messageObject.title), /* @__PURE__ */ createElement("span", { class: "secondary" }, messageObject.id)));
}
// src/Views/Objects/chatObjectView.tsx // src/Views/Objects/chatObjectView.tsx
var viewTypes = {
all: [translation.viewAll, "grid_view"],
notes: [translation.viewNotes, "sticky_note_2"]
};
function ChatObjectView(chat) { function ChatObjectView(chat) {
const isShowingObjectModal = new State(false); const isShowingObjectModal = new State(false);
const selectedObject = new State(void 0); const selectedObject = new State(void 0);
@@ -1200,36 +1280,61 @@
); );
} }
); );
const selectedViewType = new State("all");
const mainView = createProxyState([selectedViewType], () => {
function getViewFunction() {
switch (selectedViewType.value) {
case "notes":
return NoteObjectsView;
default:
return AllObjectsView;
}
}
return getViewFunction()(chat, selectedObject, isShowingObjectModal);
});
function createObject() { function createObject() {
const newObject = chat.createObjectFromTitle(translation.untitledObject); const newObject = chat.createObjectFromTitle(translation.untitledObject);
chat.addObjectAndSend(newObject); chat.addObjectAndSend(newObject);
selectedObject.value = newObject; selectedObject.value = newObject;
isShowingObjectModal.value = true; isShowingObjectModal.value = true;
} }
const objectConverter = (messageObject) => { return /* @__PURE__ */ createElement("div", { class: "chat-object-view flex-column" }, /* @__PURE__ */ createElement("div", { class: "flex-row align-center border-bottom" }, /* @__PURE__ */ createElement(
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return ObjectListEntry(messageObject, select);
};
return /* @__PURE__ */ createElement("div", { class: "chat-object-view flex-column" }, /* @__PURE__ */ createElement("div", { class: "flex-row align-center scroll-h border-bottom" }, /* @__PURE__ */ createElement(
"button", "button",
{ {
class: "primary", class: "primary height-100",
"on:click": createObject, "on:click": createObject,
"aria-label": translation.createObject "aria-label": translation.createObject
}, },
/* @__PURE__ */ createElement("span", { class: "icon" }, "add") /* @__PURE__ */ createElement("span", { class: "icon" }, "add")
), /* @__PURE__ */ createElement("div", { class: "padding-sm flex flex-row gap justify-center scroll-h width-100" }, ...Object.keys(viewTypes).map(
(key) => ViewTypeToggle(key, selectedViewType)
)), /* @__PURE__ */ createElement(
"button",
{
class: "height-100",
"on:click": createObject,
"aria-label": translation.createObject
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "visibility")
)), /* @__PURE__ */ createElement( )), /* @__PURE__ */ createElement(
"div", "div",
{ {
class: "grid gap padding", class: "width-100 height-100 flex-1 scroll-h",
style: "grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))", "children:set": mainView
"children:prepend": [chat.objects, objectConverter]
} }
), /* @__PURE__ */ createElement("div", { "children:set": objectModal })); ), /* @__PURE__ */ createElement("div", { "children:set": objectModal }));
} }
function ViewTypeToggle(key, selection) {
const [label, icon] = viewTypes[key];
function select() {
selection.value = key;
}
const isSelected = createProxyState(
[selection],
() => selection.value == key
);
return /* @__PURE__ */ createElement("button", { "aria-label": label, "on:click": select, "toggle:selected": isSelected }, /* @__PURE__ */ createElement("span", { class: "icon" }, icon));
}
// src/Views/Chat/chatOptionModal.tsx // src/Views/Chat/chatOptionModal.tsx
function ChatOptionModal(chat, isPresented) { function ChatOptionModal(chat, isPresented) {
+5 -2
View File
@@ -489,7 +489,7 @@ input[type="radio"],
} }
.justify-center { .justify-center {
justify-content: center !important; justify-content: safe center !important;
} }
.justify-end { .justify-end {
@@ -586,6 +586,10 @@ textarea,
padding: var(--control-padding) !important; padding: var(--control-padding) !important;
} }
.padding-sm {
padding: var(--gap-between-tiles) !important;
}
.modal main { .modal main {
padding: var(--modal-padding); padding: var(--modal-padding);
} }
@@ -972,7 +976,6 @@ main {
overflow-y: scroll !important; overflow-y: scroll !important;
} }
.ellipsis { .ellipsis {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
+45
View File
@@ -0,0 +1,45 @@
import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel";
import { translation } from "../../translations";
export function AllObjectsView(
chat: Chat,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
const objectConverter: React.StateItemConverter<MessageObject> = (
messageObject
) => {
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return (
<button class="tile" on:click={select}>
<div>
<b>{messageObject.title}</b>
<span class="secondary">{messageObject.id}</span>
</div>
</button>
);
};
const content = React.createProxyState([chat.objects], () =>
chat.objects.value.size == 0 ? (
<div class="flex-column width-100 height-100 align-center justify-center secondary">
{translation.noObjects}
</div>
) : (
<div
class="grid gap padding"
style="grid-template-columns: repeat(auto-fit, minmax(350px, 1fr))"
children:prepend={[chat.objects, objectConverter]}
></div>
)
);
return <div class="width-100 height-100" children:set={content}></div>;
}
+64 -17
View File
@@ -2,11 +2,18 @@ import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject } from "../../Model/chatModel";
import { AllObjectsView } from "./allObjectsView";
import { NoteObjectsView } from "./noteObjectsView";
import { ObjectDetailModal } from "./objectDetailModal"; import { ObjectDetailModal } from "./objectDetailModal";
import { ObjectListEntry } from "./objectListEntry";
import { translation } from "../../translations"; import { translation } from "../../translations";
export const viewTypes = {
all: [translation.viewAll, "grid_view"],
notes: [translation.viewNotes, "sticky_note_2"],
};
export function ChatObjectView(chat: Chat) { export function ChatObjectView(chat: Chat) {
// selection and modal
const isShowingObjectModal = new React.State(false); const isShowingObjectModal = new React.State(false);
const selectedObject = new React.State<MessageObject | undefined>(undefined); const selectedObject = new React.State<MessageObject | undefined>(undefined);
const objectModal = React.createProxyState( const objectModal = React.createProxyState(
@@ -22,6 +29,22 @@ export function ChatObjectView(chat: Chat) {
} }
); );
// view type
const selectedViewType = new React.State<keyof typeof viewTypes>("all");
const mainView = React.createProxyState([selectedViewType], () => {
function getViewFunction() {
switch (selectedViewType.value) {
case "notes":
return NoteObjectsView;
default:
return AllObjectsView;
}
}
return getViewFunction()(chat, selectedObject, isShowingObjectModal);
});
// methods
function createObject() { function createObject() {
const newObject = chat.createObjectFromTitle(translation.untitledObject); const newObject = chat.createObjectFromTitle(translation.untitledObject);
chat.addObjectAndSend(newObject); chat.addObjectAndSend(newObject);
@@ -29,36 +52,60 @@ export function ChatObjectView(chat: Chat) {
isShowingObjectModal.value = true; isShowingObjectModal.value = true;
} }
const objectConverter: React.StateItemConverter<MessageObject> = (
messageObject
) => {
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return ObjectListEntry(messageObject, select);
};
return ( return (
<div class="chat-object-view flex-column"> <div class="chat-object-view flex-column">
<div class="flex-row align-center scroll-h border-bottom"> <div class="flex-row align-center border-bottom">
<button <button
class="primary" class="primary height-100"
on:click={createObject} on:click={createObject}
aria-label={translation.createObject} aria-label={translation.createObject}
> >
<span class="icon">add</span> <span class="icon">add</span>
</button> </button>
<div class="padding-sm flex flex-row gap justify-center scroll-h width-100">
{...Object.keys(viewTypes).map((key: any) =>
ViewTypeToggle(key, selectedViewType)
)}
</div>
<button
class="height-100"
on:click={createObject}
aria-label={translation.createObject}
>
<span class="icon">visibility</span>
</button>
</div> </div>
<div <div
class="grid gap padding" class="width-100 height-100 flex-1 scroll-h"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))" children:set={mainView}
children:prepend={[chat.objects, objectConverter]}
></div> ></div>
<div children:set={objectModal}></div> <div children:set={objectModal}></div>
</div> </div>
); );
} }
function ViewTypeToggle(
key: keyof typeof viewTypes,
selection: React.State<keyof typeof viewTypes>
) {
const [label, icon] = viewTypes[key];
function select() {
selection.value = key;
}
const isSelected = React.createProxyState(
[selection],
() => selection.value == key
);
return (
<button aria-label={label} on:click={select} toggle:selected={isSelected}>
<span class="icon">{icon}</span>
</button>
);
}
+45
View File
@@ -0,0 +1,45 @@
import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel";
import { translation } from "../../translations";
export function NoteObjectsView(
chat: Chat,
selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean>
) {
const objectConverter: React.StateItemConverter<MessageObject> = (
messageObject
) => {
function select() {
selectedObject.value = messageObject;
isShowingObjectModal.value = true;
}
return (
<button class="tile" on:click={select}>
<div>
<b>{messageObject.title}</b>
<span class="secondary">{messageObject.id}</span>
</div>
</button>
);
};
const content = React.createProxyState([chat.objects], () =>
chat.objects.value.size == 0 ? (
<div class="flex-column width-100 height-100 align-center justify-center secondary">
{translation.noNotes}
</div>
) : (
<div
class="grid gap padding"
style="grid-template-columns: repeat(auto-fit, minmax(350px, 1fr))"
children:prepend={[chat.objects, objectConverter]}
></div>
)
);
return <div class="width-100 height-100" children:set={content}></div>;
}
+1
View File
@@ -83,6 +83,7 @@ export function ObjectDetailModal(
<div> <div>
<span>{translation.objectTitle}</span> <span>{translation.objectTitle}</span>
<input <input
autofocus
bind:value={editingTitle} bind:value={editingTitle}
placeholder={translation.objectTitlePlaceholder} placeholder={translation.objectTitlePlaceholder}
></input> ></input>
-17
View File
@@ -1,17 +0,0 @@
import * as React from "bloatless-react";
import { MessageObject } from "../../Model/chatModel";
export function ObjectListEntry(
messageObject: MessageObject,
onclick: () => void
) {
return (
<button class="tile" on:click={onclick}>
<div>
<b>{messageObject.title}</b>
<span class="secondary">{messageObject.id}</span>
</div>
</button>
);
}
+6
View File
@@ -71,6 +71,12 @@ const englishTranslations = {
createObject: "create object", createObject: "create object",
untitledObject: "Untitled Object", untitledObject: "Untitled Object",
viewAll: "All",
viewNotes: "Notes",
noObjects: "No objects",
noNotes: "No notes",
objectTitle: "Object title", objectTitle: "Object title",
objectTitlePlaceholder: "My object", objectTitlePlaceholder: "My object",