From 9cad9392befd03bc31b1da4d68a1ccc4f23cbd34 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Wed, 6 Apr 2022 14:02:18 -0700 Subject: [PATCH] added support for starting channels --- doc/api.oa3 | 9 +++-- net/server/internal/api_addChannel.go | 36 ++++++++++++++++--- net/server/internal/models.go | 8 +++-- net/server/internal/ucContactSync_test.go | 4 --- net/web/src/Api/addChannel.js | 10 ++++++ net/web/src/User/Contact/Contact.jsx | 8 +++++ net/web/src/User/Contact/useContact.hook.js | 2 +- .../Profile/ProfileInfo/ProfileInfo.styled.js | 2 +- .../Channels/AddChannel/AddChannel.jsx | 32 +++++++++++------ .../Channels/AddChannel/AddChannel.styled.js | 16 +++++++++ .../SideBar/Contacts/Channels/Channels.jsx | 8 ++++- .../Contacts/Channels/useChannels.hook.js | 22 ++++++++++++ .../src/User/SideBar/Contacts/Contacts.jsx | 2 +- ...Contacts.styled.jsx => Contacts.styled.js} | 0 14 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 net/web/src/Api/addChannel.js rename net/web/src/User/SideBar/Contacts/{Contacts.styled.jsx => Contacts.styled.js} (100%) diff --git a/doc/api.oa3 b/doc/api.oa3 index a83c6fa1..4f4063f3 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -3426,12 +3426,15 @@ components: ChannelParams: type: object required: - - subject + - dataType + - data - groups - cards properties: - subject: - $ref: '#/components/schemas/Subject' + dataType: + type: string + data: + type: string groups: type: array items: diff --git a/net/server/internal/api_addChannel.go b/net/server/internal/api_addChannel.go index 32452228..f3c625f0 100644 --- a/net/server/internal/api_addChannel.go +++ b/net/server/internal/api_addChannel.go @@ -9,25 +9,26 @@ import ( func AddChannel(w http.ResponseWriter, r *http.Request) { - account, code, err := BearerAppToken(r, false) + account, code, err := ParamAgentToken(r, false) if err != nil { ErrResponse(w, code, err) return } - var subject Subject - if err := ParseRequest(r, w, &subject); err != nil { + var params ChannelParams + if err := ParseRequest(r, w, ¶ms); err != nil { ErrResponse(w, http.StatusBadRequest, err) return } + cards := []*store.Card{} slot := &store.ChannelSlot{} err = store.DB.Transaction(func(tx *gorm.DB) error { channel := &store.Channel{} channel.AccountID = account.ID - channel.Data = subject.Data - channel.DataType = subject.DataType + channel.Data = params.Data + channel.DataType = params.DataType channel.DetailRevision = account.ChannelRevision + 1 channel.TopicRevision = account.ChannelRevision + 1 if res := tx.Save(channel).Error; res != nil { @@ -42,9 +43,31 @@ func AddChannel(w http.ResponseWriter, r *http.Request) { if res := tx.Save(slot).Error; res != nil { return res } + for _, cardId := range params.Cards { + cardSlot := store.CardSlot{} + if res := tx.Preload("Card").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&cardSlot).Error; res != nil { + return res + } + if res := tx.Model(&slot.Channel).Association("Cards").Append(cardSlot.Card); res != nil { + return res + } + cards = append(cards, cardSlot.Card); + } + + for _, groupId := range params.Groups { + groupSlot := store.GroupSlot{} + if res := tx.Preload("Group").Where("account_id = ? AND group_slot_id = ?", account.ID, groupId).First(&groupSlot).Error; res != nil { + return res + } + if res := tx.Model(&slot.Channel).Association("Groups").Append(groupSlot.Group); res != nil { + return res + } + } + if res := tx.Model(&account).Update("channel_revision", account.ChannelRevision + 1).Error; res != nil { return res } + return nil }) if err != nil { @@ -53,6 +76,9 @@ func AddChannel(w http.ResponseWriter, r *http.Request) { } SetStatus(account) + for _, card := range cards { + SetContactChannelNotification(account, card); + } WriteResponse(w, getChannelModel(slot, true, true)) } diff --git a/net/server/internal/models.go b/net/server/internal/models.go index 24073d59..d5bb272a 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -200,7 +200,9 @@ type ChannelMembers struct { type ChannelParams struct { - Subject *Subject `json:"subject"` + DataType string `json:"dataType"` + + Data string `json:"data"` Groups []string `json:"groups"` @@ -387,9 +389,9 @@ type SignedData struct { type Subject struct { - DataType string `json:"dataType"` + DataType string `json:"dataType"` - Data string `json:"data"` + Data string `json:"data"` } type Tag struct { diff --git a/net/server/internal/ucContactSync_test.go b/net/server/internal/ucContactSync_test.go index 49ba15db..1a995c37 100644 --- a/net/server/internal/ucContactSync_test.go +++ b/net/server/internal/ucContactSync_test.go @@ -131,10 +131,6 @@ func TestContactSync(t *testing.T) { ¶m, nil, APP_TOKENAGENT, set.A.Token, &msg, nil)) assert.NoError(t, ApiTestMsg(SetCloseMessage, "GET", "/contact/closeMessage", nil, &msg, "", "", nil, nil)) - param["cardId"] = set.D.A.CardId - assert.NoError(t, ApiTestMsg(GetCard, "GET", "/contact/cards/{cardId}", - ¶m, nil, APP_TOKENAGENT, set.D.Token, card, nil)) - assert.Nil(t, card.Data) // delete card param["cardId"] = set.A.C.CardId diff --git a/net/web/src/Api/addChannel.js b/net/web/src/Api/addChannel.js new file mode 100644 index 00000000..46a81725 --- /dev/null +++ b/net/web/src/Api/addChannel.js @@ -0,0 +1,10 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function addChannel(token, cards, subject, description ) { + let data = { subject, description }; + let params = { dataType: 'superbasic', data: JSON.stringify(data), groups: [], cards }; + let channel = await fetchWithTimeout(`/content/channels?agent=${token}`, { method: 'POST', body: JSON.stringify(params)} ); + checkResponse(channel); + return await channel.json(); +} + diff --git a/net/web/src/User/Contact/Contact.jsx b/net/web/src/User/Contact/Contact.jsx index 718d6bc6..b586394e 100644 --- a/net/web/src/User/Contact/Contact.jsx +++ b/net/web/src/User/Contact/Contact.jsx @@ -95,6 +95,13 @@ export function Contact() { return <> } + const ConfirmConnect = () => { + if (state.showButtons.confirmConnect) { + return actions.connect()}>Save & Connect + } + return <> + } + const SaveRequest = () => { if (state.showButtons.saveRequest) { return actions.saveConnect()}>Save & Connect @@ -130,6 +137,7 @@ export function Contact() { + diff --git a/net/web/src/User/Contact/useContact.hook.js b/net/web/src/User/Contact/useContact.hook.js index 834f6227..ca38e253 100644 --- a/net/web/src/User/Contact/useContact.hook.js +++ b/net/web/src/User/Contact/useContact.hook.js @@ -182,7 +182,7 @@ export function useContact() { } if (status === 'pending') { updateState({ status: 'pending' }); - updateState({ showButtons: { ignore: true, confirm: true, saveRequest: true }}); + updateState({ showButtons: { ignore: true, confirm: true, confirmConnect: true }}); } if (status === 'confirmed') { updateState({ status: 'confirmed' }); diff --git a/net/web/src/User/Profile/ProfileInfo/ProfileInfo.styled.js b/net/web/src/User/Profile/ProfileInfo/ProfileInfo.styled.js index 75e41b78..bfda8eae 100644 --- a/net/web/src/User/Profile/ProfileInfo/ProfileInfo.styled.js +++ b/net/web/src/User/Profile/ProfileInfo/ProfileInfo.styled.js @@ -18,6 +18,6 @@ export const ProfileInput = styled(Input)` export const ProfileSpin = styled(Spin)` position: absolute; - x-index: 10; + z-index: 10; `; diff --git a/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.jsx b/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.jsx index dc84838a..28176e9e 100644 --- a/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.jsx +++ b/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' -import { Button, Select, Modal } from 'antd'; -import { SelectItem } from './AddChannel.styled'; +import { Button, Select, Modal, Collapse, Input } from 'antd'; +import { SelectItem, ConversationWrapper, Description, BusySpin } from './AddChannel.styled'; import { Logo } from '../../../../../Logo/Logo'; export function AddChannel({ state, actions }) { @@ -17,14 +17,24 @@ export function AddChannel({ state, actions }) { }, [actions]); return ( - actions.setStartCards(value)} + optionLabelProp="label" + /> + + + actions.setStartSubject(e.target.value)} value={state.startSubject} /> + actions.setStartDescription(e.target.value)} value={state.startDescription} /> + + + + ) } diff --git a/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.styled.js b/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.styled.js index c94d131a..4f0be5b2 100644 --- a/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.styled.js +++ b/net/web/src/User/SideBar/Contacts/Channels/AddChannel/AddChannel.styled.js @@ -1,4 +1,11 @@ import styled from 'styled-components'; +import { Input, Spin } from 'antd'; + +export const ConversationWrapper = styled.div` + width: 100%; + display: flex; + flex-direction: column; +`; export const SelectItem = styled.div` width: 100%; @@ -6,3 +13,12 @@ export const SelectItem = styled.div` flex-direction: row; `; +export const Description = styled(Input.TextArea)` + margin-top: 16px; +`; + +export const BusySpin = styled(Spin)` + position: absolute; + z-index: 10; +` + diff --git a/net/web/src/User/SideBar/Contacts/Channels/Channels.jsx b/net/web/src/User/SideBar/Contacts/Channels/Channels.jsx index 5f2ef02a..a7b42e2f 100644 --- a/net/web/src/User/SideBar/Contacts/Channels/Channels.jsx +++ b/net/web/src/User/SideBar/Contacts/Channels/Channels.jsx @@ -8,10 +8,16 @@ export function Channels({ showAdd, setShowAdd }) { const { state, actions } = useChannels(); + const onStart = async () => { + if (await actions.addChannel()) { + setShowAdd(false); + } + } + return ( setShowAdd(false)} onCancel={() => setShowAdd(false)}> + okText="Start" onOk={() => onStart()} onCancel={() => setShowAdd(false)}> diff --git a/net/web/src/User/SideBar/Contacts/Channels/useChannels.hook.js b/net/web/src/User/SideBar/Contacts/Channels/useChannels.hook.js index 49f41300..17994344 100644 --- a/net/web/src/User/SideBar/Contacts/Channels/useChannels.hook.js +++ b/net/web/src/User/SideBar/Contacts/Channels/useChannels.hook.js @@ -1,11 +1,15 @@ import { useContext, useState, useEffect } from 'react'; import { AppContext } from '../../../../AppContext/AppContext'; import { useNavigate } from 'react-router-dom'; +import { addChannel } from '../../../../Api/addChannel'; export function useChannels() { const [state, setState] = useState({ startCards: [], + startSubject: '', + startDescription: '', + busy: false, }); const updateState = (value) => { @@ -19,6 +23,24 @@ export function useChannels() { getCardImageUrl: app?.actions?.getCardImageurl, getCards: app?.actions?.getConnectedCards, setStartCards: (cards) => updateState({ startCards: cards }), + setStartSubject: (value) => updateState({ startSubject: value }), + setStartDescription: (value) => updateState({ startDescription: value }), + addChannel: async () => { + let done = false; + if (!state.busy) { + updateState({ busy: true }); + try { + let channel = await addChannel(app.state.token, state.startCards, state.startSubject, state.startDescription); + console.log(channel); + done = true; + } + catch (err) { + window.alert(err); + } + updateState({ busy: false }); + } + return done; + } }; useEffect(() => { diff --git a/net/web/src/User/SideBar/Contacts/Contacts.jsx b/net/web/src/User/SideBar/Contacts/Contacts.jsx index 2964f895..609f5d18 100644 --- a/net/web/src/User/SideBar/Contacts/Contacts.jsx +++ b/net/web/src/User/SideBar/Contacts/Contacts.jsx @@ -46,7 +46,7 @@ export function Contacts() { } useEffect(() => { - setAddButton(addUser); + setAddButton(addConversation); }, []); return ( diff --git a/net/web/src/User/SideBar/Contacts/Contacts.styled.jsx b/net/web/src/User/SideBar/Contacts/Contacts.styled.js similarity index 100% rename from net/web/src/User/SideBar/Contacts/Contacts.styled.jsx rename to net/web/src/User/SideBar/Contacts/Contacts.styled.js