mirror of
https://github.com/balzack/databag.git
synced 2025-02-11 19:19:16 +00:00
addTopics to self hosted channels
This commit is contained in:
parent
343aa21e3e
commit
6e2801d705
@ -2113,7 +2113,7 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ChannelParams'
|
||||
|
||||
/content/channels/{channelId}:
|
||||
/content/channels/{channelId}/detail:
|
||||
get:
|
||||
tags:
|
||||
- content
|
||||
@ -2143,6 +2143,8 @@ paths:
|
||||
description: account disabled
|
||||
'500':
|
||||
description: internal server error
|
||||
|
||||
/content/channels/{channelId}:
|
||||
delete:
|
||||
tags:
|
||||
- content
|
||||
@ -2869,7 +2871,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
|
||||
|
||||
/content/channels/{channelId}/topics/{topicId}/tags:
|
||||
|
@ -16,16 +16,16 @@ func GetChannel(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var guid string
|
||||
var act *store.Account
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
tokenType := ParamTokenType(r)
|
||||
if tokenType == APP_TOKENAGENT {
|
||||
account, code, err := BearerAppToken(r, false);
|
||||
account, code, err := ParamAgentToken(r, false);
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
act = account
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
card, code, err := BearerContactToken(r, true)
|
||||
card, code, err := ParamContactToken(r, true)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
|
@ -62,16 +62,16 @@ func getChannelSlot(r *http.Request, member bool) (slot store.ChannelSlot, guid
|
||||
|
||||
// validate contact access
|
||||
var account *store.Account
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
tokenType := ParamTokenType(r);
|
||||
if tokenType == APP_TOKENAGENT {
|
||||
account, code, err = BearerAppToken(r, false);
|
||||
account, code, err = ParamAgentToken(r, false);
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
guid = account.Guid
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
var card *store.Card
|
||||
card, code, err = BearerContactToken(r, true)
|
||||
card, code, err = ParamContactToken(r, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func SetChannelTopicSubject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// load topic
|
||||
var topicSlot store.TopicSlot
|
||||
if err = store.DB.Where("channel_id = ? AND topic_slot_id = ?", channelSlot.Channel.ID, topicId).First(&topicSlot).Error; err != nil {
|
||||
if err = store.DB.Preload("Topic").Where("channel_id = ? AND topic_slot_id = ?", channelSlot.Channel.ID, topicId).First(&topicSlot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
|
@ -541,7 +541,7 @@ var routes = Routes{
|
||||
Route{
|
||||
"GetChannel",
|
||||
strings.ToUpper("Get"),
|
||||
"/content/channels/{channelId}",
|
||||
"/content/channels/{channelId}/detail",
|
||||
GetChannel,
|
||||
},
|
||||
|
||||
|
@ -196,18 +196,28 @@ func ApiTestUpload(
|
||||
return
|
||||
}
|
||||
|
||||
if tokenType == APP_TOKENAGENT {
|
||||
if !strings.Contains(name, "?") {
|
||||
name += "?"
|
||||
} else {
|
||||
name += "&"
|
||||
}
|
||||
name += "agent=" + token
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
if !strings.Contains(name, "?") {
|
||||
name += "?"
|
||||
} else {
|
||||
name += "&"
|
||||
}
|
||||
name += "contact=" + token
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(requestType, name, &data)
|
||||
|
||||
if params != nil {
|
||||
r = mux.SetURLVars(r, *params)
|
||||
}
|
||||
if tokenType != "" {
|
||||
r.Header.Add("TokenType", tokenType)
|
||||
}
|
||||
if token != "" {
|
||||
SetBearerAuth(r, token)
|
||||
}
|
||||
r.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
endpoint(w, r)
|
||||
|
||||
|
24
net/web/src/Api/addChannelTopic.js
Normal file
24
net/web/src/Api/addChannelTopic.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addChannelTopic(token, channelId, message, assets ) {
|
||||
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`,
|
||||
{ method: 'POST', body: JSON.stringify({}) });
|
||||
checkResponse(topic);
|
||||
let slot = await topic.json();
|
||||
|
||||
// add each asset
|
||||
|
||||
let subject = { data: JSON.stringify(message, (key, value) => {
|
||||
if (value !== null) return value
|
||||
}), datatype: 'superbasictopic' };
|
||||
let unconfirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/subject?agent=${token}`,
|
||||
{ method: 'PUT', body: JSON.stringify(subject) });
|
||||
checkResponse(unconfirmed);
|
||||
|
||||
let confirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/confirmed?agent=${token}`,
|
||||
{ method: 'PUT', body: JSON.stringify('confirmed') });
|
||||
checkResponse(confirmed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
8
net/web/src/Api/getChannel.js
Normal file
8
net/web/src/Api/getChannel.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function getChannel(token, channelId) {
|
||||
let channel = await fetchWithTimeout(`/content/channels/${channelId}/detail?agent=${token}`, { method: 'GET' });
|
||||
checkResponse(channel)
|
||||
return await channel.json()
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
export async function getChannels(token, revision) {
|
||||
let param = "?agent=" + token
|
||||
if (revision != null) {
|
||||
param += '&revision=' + revision
|
||||
param += '&channelRevision=' + revision
|
||||
}
|
||||
let channels = await fetchWithTimeout('/content/channels' + param, { method: 'GET' });
|
||||
checkResponse(channels)
|
||||
|
@ -26,7 +26,8 @@ function App() {
|
||||
<Route path="/user" element={ <User /> }>
|
||||
<Route path="profile" element={<Profile />} />
|
||||
<Route path="contact/:guid" element={<Contact />} />
|
||||
<Route path="conversation/:id" element={<Conversation />} />
|
||||
<Route path="conversation/:contact/:channel" element={<Conversation />} />
|
||||
<Route path="conversation/:channel" element={<Conversation />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Router>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { getContactProfile, setCardProfile, getCards, getCardImageUrl, getCardProfile, getCardDetail, getListingImageUrl, getListing, setProfileImage, setProfileData, getProfileImageUrl, getAccountStatus, setAccountSearchable, getProfile, getGroups, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
|
||||
import { getChannels } from '../Api/getChannels';
|
||||
import { getChannel } from '../Api/getChannel';
|
||||
import { getContactChannels } from '../Api/getContactChannels';
|
||||
|
||||
async function updateAccount(token, updateData) {
|
||||
@ -30,7 +31,22 @@ async function updateChannels(token, revision, channelMap, mergeChannels) {
|
||||
let channels = await getChannels(token, revision);
|
||||
for (let channel of channels) {
|
||||
if (channel.data) {
|
||||
channelMap.set(channel.id, channel);
|
||||
let cur = channelMap.get(channel.id);
|
||||
if (cur == null) {
|
||||
cur = { id: channel.id, data: { } }
|
||||
}
|
||||
if (cur.data.detailRevision != channel.data.detailRevision) {
|
||||
if (channel.data.channelDetail != null) {
|
||||
cur.data.channelDetail = channel.data.channelDetail;
|
||||
cur.data.detailRevision = channel.data.detailRevision;
|
||||
}
|
||||
else {
|
||||
let slot = await getChannel(token, channel.id);
|
||||
cur.data.channelDetail = slot.data.channelDetail;
|
||||
cur.data.detailRevision = slot.data.detailRevision;
|
||||
}
|
||||
}
|
||||
channelMap.set(channel.id, cur);
|
||||
}
|
||||
else {
|
||||
channelMap.delete(channel.id);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, Dropdown, Input, Tooltip, Menu } from 'antd';
|
||||
import { AddTopicWrapper } from './AddTopic.styled';
|
||||
import { AddTopicWrapper, BusySpin } from './AddTopic.styled';
|
||||
import { AddCarousel } from './AddCarousel/AddCarousel';
|
||||
import { useAddTopic } from './useAddTopic.hook';
|
||||
import { BgColorsOutlined, FontColorsOutlined, FontSizeOutlined, PaperClipOutlined, SendOutlined } from '@ant-design/icons';
|
||||
@ -9,11 +9,6 @@ export function AddTopic() {
|
||||
|
||||
const { state, actions } = useAddTopic();
|
||||
|
||||
const onAttach = () => {
|
||||
console.log("ADD IMAGE");
|
||||
actions.addImage(null);
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="0">
|
||||
@ -28,6 +23,10 @@ export function AddTopic() {
|
||||
</Menu>
|
||||
);
|
||||
|
||||
const onSend = () => {
|
||||
actions.addTopic();
|
||||
}
|
||||
|
||||
return (
|
||||
<AddTopicWrapper>
|
||||
<div class="container noselect">
|
||||
@ -52,7 +51,8 @@ export function AddTopic() {
|
||||
<Button icon={<BgColorsOutlined />} size="large" />
|
||||
</div>
|
||||
<div class="send">
|
||||
<Button icon={<SendOutlined />} size="large" />
|
||||
<Button icon={<SendOutlined />} onClick={onSend} size="large" />
|
||||
<BusySpin spinning={state.busy} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Spin } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const AddTopicWrapper = styled.div`
|
||||
@ -35,7 +36,14 @@ export const AddTopicWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding-top: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const BusySpin = styled(Spin)`
|
||||
position: absolute;
|
||||
margin-right: 12px;
|
||||
x-index: 10;
|
||||
`;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { addChannelTopic } from '../../../Api/addChannelTopic';
|
||||
import { AppContext } from '../../../AppContext/AppContext';
|
||||
|
||||
export function useAddTopic() {
|
||||
|
||||
@ -7,11 +9,14 @@ export function useAddTopic() {
|
||||
assets: [],
|
||||
messageText: null,
|
||||
messageColor: null,
|
||||
messageWeight: null,
|
||||
messageSize: null,
|
||||
backgroundColor: null,
|
||||
busy: false,
|
||||
});
|
||||
|
||||
const { contact, channel } = useParams();
|
||||
const app = useContext(AppContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
@ -23,8 +28,6 @@ export function useAddTopic() {
|
||||
});
|
||||
}
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const actions = {
|
||||
addImage: (image) => { addAsset(image) },
|
||||
addVideo: (video) => { addAsset(video) },
|
||||
@ -46,7 +49,22 @@ export function useAddTopic() {
|
||||
setBackgroundColor: (value) => {
|
||||
updateState({ backgroundColor: value });
|
||||
},
|
||||
addTopic: () => {},
|
||||
addTopic: async () => {
|
||||
if (!state.busy) {
|
||||
updateState({ busy: true });
|
||||
try {
|
||||
if (!contact) {
|
||||
let message = { text: state.messageText, textColor: state.messageColor,
|
||||
textSize: state.messageSize, backgroundColor: state.backgroundColor };
|
||||
await addChannelTopic(app.state.token, channel, message, []);
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
window.alert(err);
|
||||
}
|
||||
updateState({ busy: false });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
@ -8,7 +8,7 @@ export function useConversation() {
|
||||
});
|
||||
|
||||
const data = useLocation();
|
||||
const { id } = useParams();
|
||||
const { contact, channel } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const app = useContext(AppContext);
|
||||
|
||||
@ -22,11 +22,5 @@ export function useConversation() {
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (app?.state?.access === 'user') {
|
||||
console.log("CONVERSATION:", id);
|
||||
}
|
||||
}, [app, id])
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -14,7 +14,12 @@ export function useChannelItem() {
|
||||
|
||||
const actions = {
|
||||
select: (item) => {
|
||||
navigate(`/user/conversation/${item.channel.id}`);
|
||||
if (item.guid) {
|
||||
navigate(`/user/conversation/${item.guid}/${item.channel.id}`);
|
||||
}
|
||||
else {
|
||||
navigate(`/user/conversation/${item.channel.id}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user