mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
49e04c11c6
No reason to incldue daml-trigger by default. changelog_begin changelog_end
250 lines
8.1 KiB
Diff
250 lines
8.1 KiB
Diff
diff --git create-daml-app/daml/ChatBot.daml create-daml-app/daml/ChatBot.daml
|
|
--- create-daml-app/daml/ChatBot.daml 1970-01-01 01:00:00.000000000 +0100
|
|
+++ create-daml-app/daml/ChatBot.daml 2022-01-12 17:55:45.838308273 +0100
|
|
@@ -0,0 +1,29 @@
|
|
+module ChatBot where
|
|
+
|
|
+import qualified Daml.Trigger as T
|
|
+import qualified User
|
|
+import qualified DA.List.Total as List
|
|
+import DA.Action (when)
|
|
+import DA.Optional (whenSome)
|
|
+
|
|
+autoReply : T.Trigger ()
|
|
+autoReply = T.Trigger
|
|
+ { initialize = pure ()
|
|
+ , updateState = \_ -> pure ()
|
|
+ , rule = \p -> do
|
|
+ message_contracts <- T.query @User.Message
|
|
+ let messages = map snd message_contracts
|
|
+ debug $ "Messages so far: " <> show (length messages)
|
|
+ let lastMessage = List.maximumOn (.receivedAt) messages
|
|
+ debug $ "Last message: " <> show lastMessage
|
|
+ whenSome lastMessage $ \m ->
|
|
+ when (m.receiver == p) $ do
|
|
+ users <- T.query @User.User
|
|
+ debug users
|
|
+ let isSender = (\user -> user.username == m.sender)
|
|
+ let replyTo = List.head $ filter (\(_, user) -> isSender user) users
|
|
+ whenSome replyTo $ \(sender, _) ->
|
|
+ T.dedupExercise sender (User.SendMessage p "Please, tell me more about that.")
|
|
+ , registeredTemplates = T.AllInDar
|
|
+ , heartbeat = None
|
|
+ }
|
|
diff --git create-daml-app/daml/NoOp.daml create-daml-app/daml/NoOp.daml
|
|
--- create-daml-app/daml/NoOp.daml 1970-01-01 01:00:00.000000000 +0100
|
|
+++ create-daml-app/daml/NoOp.daml 2022-01-12 17:55:45.838308273 +0100
|
|
@@ -0,0 +1,13 @@
|
|
+module NoOp where
|
|
+
|
|
+import qualified Daml.Trigger as T
|
|
+
|
|
+noOp : T.Trigger ()
|
|
+noOp = T.Trigger with
|
|
+ initialize = pure ()
|
|
+ updateState = \_ -> pure ()
|
|
+ rule = \_ -> do
|
|
+ debug "triggered"
|
|
+ pure ()
|
|
+ registeredTemplates = T.AllInDar
|
|
+ heartbeat = None
|
|
diff --git create-daml-app/daml/User.daml create-daml-app/daml/User.daml
|
|
--- create-daml-app/daml/User.daml 2022-01-12 17:55:49.754285111 +0100
|
|
+++ create-daml-app/daml/User.daml 2022-01-12 17:55:45.838308273 +0100
|
|
@@ -26,6 +25,17 @@
|
|
archive self
|
|
create this with following = userToFollow :: following
|
|
-- FOLLOW_END
|
|
+ -- SEND_BEGIN
|
|
+ -- New definition for SendMessage
|
|
+ nonconsuming choice SendMessage: ContractId Message with
|
|
+ sender: Party
|
|
+ content: Text
|
|
+ controller sender
|
|
+ do
|
|
+ assertMsg "Designated user must follow you back to send a message" (elem sender following)
|
|
+ now <- getTime
|
|
+ create Message with sender, receiver = username, content, receivedAt = now
|
|
+ -- SEND_END
|
|
|
|
-- ALIAS_BEGIN
|
|
template Alias with
|
|
@@ -46,3 +56,13 @@
|
|
archive self
|
|
create this with alias = newAlias
|
|
-- ALIAS_END
|
|
+
|
|
+-- MESSAGE_BEGIN
|
|
+template Message with
|
|
+ sender: Party
|
|
+ receiver: Party
|
|
+ content: Text
|
|
+ receivedAt: Time
|
|
+ where
|
|
+ signatory sender, receiver
|
|
+-- MESSAGE_END
|
|
--- create-daml-app/daml.yaml.template 2022-01-26 17:29:37.149557361 +0100
|
|
+++ create-daml-app/daml.yaml.template 2022-01-26 17:29:27.749276386 +0100
|
|
@@ -2,10 +2,13 @@
|
|
name: __PROJECT_NAME__
|
|
version: 0.1.0
|
|
source: daml
|
|
+# trigger-dependencies-begin
|
|
dependencies:
|
|
- daml-prim
|
|
- daml-stdlib
|
|
- daml-script
|
|
+- daml-trigger
|
|
+# trigger-dependencies-end
|
|
start-navigator: false
|
|
codegen:
|
|
js:
|
|
diff --git create-daml-app/ui/src/components/MainView.tsx.template create-daml-app/ui/src/components/MainView.tsx.template
|
|
--- create-daml-app/ui/src/components/MainView.tsx.template
|
|
+++ create-daml-app/ui/src/components/MainView.tsx.template
|
|
@@ -8,6 +8,10 @@
|
|
import { publicContext, userContext } from './App';
|
|
import UserList from './UserList';
|
|
import PartyListEdit from './PartyListEdit';
|
|
+// IMPORTS_BEGIN
|
|
+import MessageEdit from './MessageEdit';
|
|
+import MessageList from './MessageList';
|
|
+// IMPORTS_END
|
|
|
|
// USERS_BEGIN
|
|
const MainView: React.FC = () => {
|
|
@@ -88,6 +92,22 @@
|
|
/>
|
|
{/* USERLIST_END */}
|
|
</Segment>
|
|
+ {/* MESSAGES_SEGMENT_BEGIN */}
|
|
+ <Segment>
|
|
+ <Header as='h2'>
|
|
+ <Icon name='pencil square' />
|
|
+ <Header.Content>
|
|
+ Messages
|
|
+ <Header.Subheader>Send a message to a follower</Header.Subheader>
|
|
+ </Header.Content>
|
|
+ </Header>
|
|
+ <MessageEdit
|
|
+ followers={followers.map(follower => follower.username)}
|
|
+ />
|
|
+ <Divider />
|
|
+ <MessageList />
|
|
+ </Segment>
|
|
+ {/* MESSAGES_SEGMENT_END */}
|
|
</Grid.Column>
|
|
</Grid.Row>
|
|
</Grid>
|
|
diff --git create-daml-app/ui/src/components/MessageEdit.tsx.template create-daml-app/ui/src/components/MessageEdit.tsx.template
|
|
--- /dev/null
|
|
+++ create-daml-app/ui/src/components/MessageEdit.tsx.template
|
|
@@ -0,0 +1,70 @@
|
|
+// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+
|
|
+// MESSAGEEDIT_BEGIN
|
|
+import React from 'react'
|
|
+import { Form, Button } from 'semantic-ui-react';
|
|
+import { Party } from '@daml/types';
|
|
+import { User } from '@daml.js/__PROJECT_NAME__';
|
|
+import { userContext } from './App';
|
|
+
|
|
+type Props = {
|
|
+ followers: Party[];
|
|
+}
|
|
+
|
|
+/**
|
|
+ * React component to edit a message to send to a follower.
|
|
+ */
|
|
+const MessageEdit: React.FC<Props> = ({followers}) => {
|
|
+ const sender = userContext.useParty();
|
|
+ const [receiver, setReceiver] = React.useState<string | undefined>();
|
|
+ const [content, setContent] = React.useState("");
|
|
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
+ const ledger = userContext.useLedger();
|
|
+
|
|
+ const submitMessage = async (event: React.FormEvent) => {
|
|
+ try {
|
|
+ event.preventDefault();
|
|
+ if (receiver === undefined) {
|
|
+ return;
|
|
+ }
|
|
+ setIsSubmitting(true);
|
|
+ await ledger.exerciseByKey(User.User.SendMessage, receiver, {sender, content});
|
|
+ setContent("");
|
|
+ } catch (error) {
|
|
+ alert(`Error sending message:\n${JSON.stringify(error)}`);
|
|
+ } finally {
|
|
+ setIsSubmitting(false);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ return (
|
|
+ <Form onSubmit={submitMessage}>
|
|
+ <Form.Dropdown
|
|
+ selection
|
|
+ className='test-select-message-receiver'
|
|
+ placeholder="Select a follower"
|
|
+ options={followers.map(follower => ({ key: follower, text: follower, value: follower }))}
|
|
+ value={receiver}
|
|
+ onChange={event => setReceiver(event.currentTarget.textContent ?? undefined)}
|
|
+ />
|
|
+ <Form.Input
|
|
+ className='test-select-message-content'
|
|
+ placeholder="Write a message"
|
|
+ value={content}
|
|
+ onChange={event => setContent(event.currentTarget.value)}
|
|
+ />
|
|
+ <Button
|
|
+ fluid
|
|
+ className='test-select-message-send-button'
|
|
+ type="submit"
|
|
+ disabled={isSubmitting || receiver === undefined || content === ""}
|
|
+ loading={isSubmitting}
|
|
+ content="Send"
|
|
+ />
|
|
+ </Form>
|
|
+ );
|
|
+};
|
|
+
|
|
+export default MessageEdit;
|
|
+// MESSAGEEDIT_END
|
|
diff --git create-daml-app/ui/src/components/MessageList.tsx.template create-daml-app/ui/src/components/MessageList.tsx.template
|
|
--- /dev/null
|
|
+++ create-daml-app/ui/src/components/MessageList.tsx.template 2022-01-12 17:55:45.834308296 +0100
|
|
@@ -0,0 +1,33 @@
|
|
+// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+
|
|
+// MESSAGELIST_BEGIN
|
|
+import React from 'react'
|
|
+import { List, ListItem } from 'semantic-ui-react';
|
|
+import { User } from '@daml.js/__PROJECT_NAME__';
|
|
+import { userContext } from './App';
|
|
+
|
|
+/**
|
|
+ * React component displaying the list of messages for the current user.
|
|
+ */
|
|
+const MessageList: React.FC = () => {
|
|
+ const messagesResult = userContext.useStreamQueries(User.Message);
|
|
+
|
|
+ return (
|
|
+ <List relaxed>
|
|
+ {messagesResult.contracts.map(message => {
|
|
+ const {sender, receiver, content} = message.payload;
|
|
+ return (
|
|
+ <ListItem
|
|
+ className='test-select-message-item'
|
|
+ key={message.contractId}>
|
|
+ <strong>{sender} → {receiver}:</strong> {content}
|
|
+ </ListItem>
|
|
+ );
|
|
+ })}
|
|
+ </List>
|
|
+ );
|
|
+};
|
|
+
|
|
+export default MessageList;
|
|
+// MESSAGELIST_END
|