added support for starting channels

This commit is contained in:
Roland Osborne 2022-04-06 14:02:18 -07:00
parent e80eb49036
commit 9cad9392be
14 changed files with 129 additions and 30 deletions

View File

@ -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:

View File

@ -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, &params); 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))
}

View File

@ -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"`

View File

@ -131,10 +131,6 @@ func TestContactSync(t *testing.T) {
&param, 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}",
&param, nil, APP_TOKENAGENT, set.D.Token, card, nil))
assert.Nil(t, card.Data)
// delete card
param["cardId"] = set.A.C.CardId

View File

@ -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();
}

View File

@ -95,6 +95,13 @@ export function Contact() {
return <></>
}
const ConfirmConnect = () => {
if (state.showButtons.confirmConnect) {
return <ProfileButton ghost onClick={() => actions.connect()}>Save & Connect</ProfileButton>
}
return <></>
}
const SaveRequest = () => {
if (state.showButtons.saveRequest) {
return <ProfileButton ghost onClick={() => actions.saveConnect()}>Save & Connect</ProfileButton>
@ -130,6 +137,7 @@ export function Contact() {
<Ignore />
<Deny />
<Save />
<ConfirmConnect />
<SaveRequest />
<Connect />
<Accept />

View File

@ -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' });

View File

@ -18,6 +18,6 @@ export const ProfileInput = styled(Input)`
export const ProfileSpin = styled(Spin)`
position: absolute;
x-index: 10;
z-index: 10;
`;

View File

@ -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 (
<ConversationWrapper>
<Select
mode="multiple"
style={{ width: '100%' }}
placeholder="Select Contacts"
defaultValue={[]}
options={options}
onChange={(value) => console.log(value)}
onChange={(value) => actions.setStartCards(value)}
optionLabelProp="label"
/>
<Collapse ghost="true">
<Collapse.Panel header="Conversation Details (optional)" key="1">
<Input placeholder="Subject" onChange={(e) => actions.setStartSubject(e.target.value)} value={state.startSubject} />
<Description placeholder="Description" autoSize={{ minRows: 2, maxRows: 6 }}
onChange={(e) => actions.setStartDescription(e.target.value)} value={state.startDescription} />
</Collapse.Panel>
</Collapse>
<BusySpin size="large" spinning={state.busy} />
</ConversationWrapper>
)
}

View File

@ -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;
`

View File

@ -8,10 +8,16 @@ export function Channels({ showAdd, setShowAdd }) {
const { state, actions } = useChannels();
const onStart = async () => {
if (await actions.addChannel()) {
setShowAdd(false);
}
}
return (
<ChannelsWrapper>
<Modal title="Start Conversation" visible={showAdd} centered
onOk={() => setShowAdd(false)} onCancel={() => setShowAdd(false)}>
okText="Start" onOk={() => onStart()} onCancel={() => setShowAdd(false)}>
<AddChannel state={state} actions={actions} />
</Modal>
</ChannelsWrapper>

View File

@ -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(() => {

View File

@ -46,7 +46,7 @@ export function Contacts() {
}
useEffect(() => {
setAddButton(addUser);
setAddButton(addConversation);
}, []);
return (