adding channel summary method

This commit is contained in:
Roland Osborne 2022-05-09 14:08:54 -07:00
parent 0416389be0
commit 8e14f51d58
13 changed files with 267 additions and 12 deletions

View File

@ -2144,6 +2144,37 @@ paths:
'500': '500':
description: internal server error description: internal server error
/content/channels/{channelId}/summary:
get:
tags:
- content
description: Get summary of channel.
operationId: get-channel-summary
security:
- bearerAuth: []
parameters:
- name: channelId
in: path
description: specified channel id
required: true
schema:
type: string
responses:
'200':
description: success
content:
application/json:
schema:
$ref: '#/components/schemas/ChannelSummary'
'401':
description: invalid password
'404':
description: channel not found
'410':
description: account disabled
'500':
description: internal server error
/content/channels/{channelId}: /content/channels/{channelId}:
delete: delete:
tags: tags:
@ -3439,6 +3470,8 @@ components:
topicRevision: topicRevision:
type: integer type: integer
format: int64 format: int64
channelSummary:
$ref: '#/components/schemas/ChannelSummary'
channelDetail: channelDetail:
$ref: '#/components/schemas/ChannelDetail' $ref: '#/components/schemas/ChannelDetail'
@ -3467,6 +3500,12 @@ components:
items: items:
type: string type: string
ChannelSummary:
type: object
properties:
lastTopic:
$ref: '#/components/schemas/TopicDetail'
ChannelContacts: ChannelContacts:
type: object type: object
required: required:

View File

@ -0,0 +1,63 @@
package databag
import (
"errors"
"net/http"
"gorm.io/gorm"
"github.com/gorilla/mux"
"databag/internal/store"
)
func GetChannelDetail(w http.ResponseWriter, r *http.Request) {
// scan parameters
params := mux.Vars(r)
channelId := params["channelId"]
var guid string
var act *store.Account
tokenType := ParamTokenType(r)
if tokenType == APP_TOKENAGENT {
account, code, err := ParamAgentToken(r, false);
if err != nil {
ErrResponse(w, code, err)
return
}
act = account
} else if tokenType == APP_TOKENCONTACT {
card, code, err := ParamContactToken(r, true)
if err != nil {
ErrResponse(w, code, err)
return
}
act = &card.Account
guid = card.Guid
} else {
ErrResponse(w, http.StatusBadRequest, errors.New("unknown token type"))
return
}
// load channel
var slot store.ChannelSlot
if err := store.DB.Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.Cards").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_slot_id = ?", act.ID, channelId).First(&slot).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusNotFound, err)
} else {
ErrResponse(w, http.StatusInternalServerError, err)
}
return
}
// return model data
if guid != "" {
if isChannelShared(guid, slot.Channel) {
WriteResponse(w, getChannelDetailModel(&slot, false))
} else {
ErrResponse(w, http.StatusNotFound, errors.New("channel not shared with requestor"));
return
}
} else {
WriteResponse(w, getChannelDetailModel(&slot, true))
}
}

View File

@ -0,0 +1,65 @@
package databag
import (
"errors"
"net/http"
"gorm.io/gorm"
"github.com/gorilla/mux"
"databag/internal/store"
)
func GetChannelSummary(w http.ResponseWriter, r *http.Request) {
// scan parameters
params := mux.Vars(r)
channelId := params["channelId"]
var guid string
var act *store.Account
tokenType := ParamTokenType(r)
if tokenType == APP_TOKENAGENT {
account, code, err := ParamAgentToken(r, false);
if err != nil {
ErrResponse(w, code, err)
return
}
act = account
} else if tokenType == APP_TOKENCONTACT {
card, code, err := ParamContactToken(r, true)
if err != nil {
ErrResponse(w, code, err)
return
}
act = &card.Account
guid = card.Guid
} else {
ErrResponse(w, http.StatusBadRequest, errors.New("unknown token type"))
return
}
// load channel
var slot store.ChannelSlot
if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB {
return store.DB.Order("topics.id DESC").Limit(1)
}).Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.Cards").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_slot_id = ?", act.ID, channelId).First(&slot).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusNotFound, err)
} else {
ErrResponse(w, http.StatusInternalServerError, err)
}
return
}
// return model data
if guid != "" {
if isChannelShared(guid, slot.Channel) {
WriteResponse(w, getChannelSummaryModel(&slot))
} else {
ErrResponse(w, http.StatusNotFound, errors.New("channel not shared with requestor"));
return
}
} else {
WriteResponse(w, getChannelSummaryModel(&slot))
}
}

View File

@ -66,7 +66,9 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
return return
} }
} else { } else {
if err := store.DB.Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil { if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB {
return store.DB.Order("topics.id DESC").Limit(1)
}).Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
@ -102,14 +104,14 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
account := &card.Account account := &card.Account
var slots []store.ChannelSlot var slots []store.ChannelSlot
if channelRevisionSet { if channelRevisionSet {
if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB { if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
return store.DB.Order("topics.id DESC").Limit(1)
}).Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
} else { } else {
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil { if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB {
return store.DB.Order("topics.id DESC").Limit(1)
}).Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }

View File

@ -199,6 +199,27 @@ func getChannelDetailModel(slot *store.ChannelSlot, showList bool) *ChannelDetai
} }
} }
func getChannelSummaryModel(slot *store.ChannelSlot) *ChannelSummary {
if slot.Channel == nil {
return nil
}
topicDetail := TopicDetail{};
if len(slot.Channel.Topics) > 0 {
topicDetail.Guid = slot.Channel.Topics[0].Guid;
topicDetail.DataType = slot.Channel.Topics[0].DataType;
topicDetail.Data = slot.Channel.Topics[0].Data;
topicDetail.Created = slot.Channel.Topics[0].Created;
topicDetail.Updated = slot.Channel.Topics[0].Updated;
topicDetail.Status = slot.Channel.Topics[0].Status;
}
return &ChannelSummary{
LastTopic: &topicDetail,
}
}
func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Channel { func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Channel {
if !showData || slot.Channel == nil { if !showData || slot.Channel == nil {
@ -215,6 +236,7 @@ func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Cha
DetailRevision: slot.Channel.DetailRevision, DetailRevision: slot.Channel.DetailRevision,
TopicRevision: slot.Channel.TopicRevision, TopicRevision: slot.Channel.TopicRevision,
ChannelDetail: getChannelDetailModel(slot, showList), ChannelDetail: getChannelDetailModel(slot, showList),
ChannelSummary: getChannelSummaryModel(slot),
}, },
} }
} }

View File

@ -175,6 +175,8 @@ type ChannelData struct {
TopicRevision int64 `json:"topicRevision"` TopicRevision int64 `json:"topicRevision"`
ChannelSummary *ChannelSummary `json:"channelSummary,omitempty"`
ChannelDetail *ChannelDetail `json:"channelDetail,omitempty"` ChannelDetail *ChannelDetail `json:"channelDetail,omitempty"`
} }
@ -193,6 +195,11 @@ type ChannelDetail struct {
Members []string `json:"members"` Members []string `json:"members"`
} }
type ChannelSummary struct {
LastTopic *TopicDetail `json:"lastTopic,omitempty"`
}
type ChannelParams struct { type ChannelParams struct {
DataType string `json:"dataType"` DataType string `json:"dataType"`
@ -443,7 +450,7 @@ type TopicDetail struct {
Status string `json:"status"` Status string `json:"status"`
Transform string `json:"transform"` Transform string `json:"transform,omitempty"`
} }
type TopicTags struct { type TopicTags struct {

View File

@ -545,6 +545,13 @@ var routes = Routes{
GetChannelDetail, GetChannelDetail,
}, },
Route{
"GetChannelSummary",
strings.ToUpper("Get"),
"/content/channels/{channelId}/summary",
GetChannelSummary,
},
Route{ Route{
"GetChannelSubjectField", "GetChannelSubjectField",
strings.ToUpper("Get"), strings.ToUpper("Get"),

View File

@ -0,0 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelDetail(token, channelId) {
let detail = await fetchWithTimeout(`/content/channels/${channelId}/detail?agent=${token}`, { method: 'GET' });
checkResponse(detail)
return await detail.json()
}

View File

@ -0,0 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getChannelSummary(token, channelId) {
let summary = await fetchWithTimeout(`/content/channels/${channelId}/summary?agent=${token}`, { method: 'GET' });
checkResponse(summary)
return await summary.json()
}

View File

@ -0,0 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelDetail(token, channelId) {
let detail = await fetchWithTimeout(`/content/channels/${channelId}/detail?contact=${token}`, { method: 'GET' });
checkResponse(detail)
return await detail.json()
}

View File

@ -0,0 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelSummary(token, channelId) {
let summary = await fetchWithTimeout(`/content/channels/${channelId}/summary?contact=${token}`, { method: 'GET' });
checkResponse(summary)
return await summary.json()
}

View File

@ -1,6 +1,7 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import { getContactChannels } from 'api/getContactChannels'; import { getContactChannels } from 'api/getContactChannels';
import { getContactChannelDetail } from 'api/getContactChannelDetail'; import { getContactChannelDetail } from 'api/getContactChannelDetail';
import { getContactChannelSummary } from 'api/getContactChannelSummary';
import { getContactProfile } from 'api/getContactProfile'; import { getContactProfile } from 'api/getContactProfile';
import { setCardProfile } from 'api/setCardProfile'; import { setCardProfile } from 'api/setCardProfile';
import { getCards } from 'api/getCards'; import { getCards } from 'api/getCards';
@ -116,15 +117,23 @@ export function useCardContext() {
if (cur.data.detailRevision != channel.data.detailRevision) { if (cur.data.detailRevision != channel.data.detailRevision) {
if (channel.data.channelDetail != null) { if (channel.data.channelDetail != null) {
cur.data.channelDetail = channel.data.channelDetail; cur.data.channelDetail = channel.data.channelDetail;
cur.data.detailRevision = channel.data.detailRevision;
} }
else { else {
let detail = await getContactChannelDetail(guid + "." + token, channel.id); let detail = await getContactChannelDetail(guid + "." + token, channel.id);
cur.data.channelDetail = detail; cur.data.channelDetail = detail;
cur.data.detailRevision = channel.data.detailRevision;
} }
cur.data.detailRevision = channel.data.detailRevision;
}
if (cur.data.detailRevision != channel.data.detailRevision) {
if (channel.data.channelSummary != null) {
cur.data.channelSummary = channel.data.channelSummary;
}
else {
let summary = await getContactChannelSummary(guid + "." + token, channel.id);
cur.data.channelSummary = summary;
}
cur.data.topicRevision = channel.data.topicRevision;
} }
cur.data.topicRevision = channel.data.topicRevision;
cur.revision = channel.revision; cur.revision = channel.revision;
channelMap.set(channel.id, cur); channelMap.set(channel.id, cur);
} }

View File

@ -1,6 +1,7 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import { getChannels } from 'api/getChannels'; import { getChannels } from 'api/getChannels';
import { getChannelDetail } from 'api/getChannelDetail'; import { getChannelDetail } from 'api/getChannelDetail';
import { getChannelSummary } from 'api/getChannelSummary';
import { addChannel } from 'api/addChannel'; import { addChannel } from 'api/addChannel';
import { addChannelTopic } from 'api/addChannelTopic'; import { addChannelTopic } from 'api/addChannelTopic';
import { getChannelTopics } from 'api/getChannelTopics'; import { getChannelTopics } from 'api/getChannelTopics';
@ -32,15 +33,23 @@ export function useChannelContext() {
if (cur.data.detailRevision != channel.data.detailRevision) { if (cur.data.detailRevision != channel.data.detailRevision) {
if (channel.data.channelDetail != null) { if (channel.data.channelDetail != null) {
cur.data.channelDetail = channel.data.channelDetail; cur.data.channelDetail = channel.data.channelDetail;
cur.data.detailRevision = channel.data.detailRevision;
} }
else { else {
let detail = await getChannelDetail(access.current, channel.id); let detail = await getChannelDetail(access.current, channel.id);
cur.data.channelDetail = detail; cur.data.channelDetail = detail;
cur.data.detailRevision = channel.data.detailRevision;
} }
cur.data.detailRevision = channel.data.detailRevision;
}
if (cur.data.topicRevision != channel.data.topicRevision) {
if (channel.data.channelDetail != null) {
cur.data.channelDetail = channel.data.channelDetail;
}
else {
let summary = await getChannelSummary(access.current, channel.id);
cur.data.channelSummary = summary;
}
cur.data.topicRevision = channel.data.topicRevision;
} }
cur.data.topicRevision = channel.data.topicRevision;
cur.revision = channel.revision; cur.revision = channel.revision;
channels.current.set(channel.id, cur); channels.current.set(channel.id, cur);
} }