Merge branch 'master' into PLT-340
Этот коммит содержится в:
55
model/analytics_row.go
Обычный файл
55
model/analytics_row.go
Обычный файл
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type AnalyticsRow struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
}
|
||||
|
||||
type AnalyticsRows []*AnalyticsRow
|
||||
|
||||
func (me *AnalyticsRow) ToJson() string {
|
||||
b, err := json.Marshal(me)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func AnalyticsRowFromJson(data io.Reader) *AnalyticsRow {
|
||||
decoder := json.NewDecoder(data)
|
||||
var me AnalyticsRow
|
||||
err := decoder.Decode(&me)
|
||||
if err == nil {
|
||||
return &me
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (me AnalyticsRows) ToJson() string {
|
||||
if b, err := json.Marshal(me); err != nil {
|
||||
return "[]"
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func AnalyticsRowsFromJson(data io.Reader) AnalyticsRows {
|
||||
decoder := json.NewDecoder(data)
|
||||
var me AnalyticsRows
|
||||
err := decoder.Decode(&me)
|
||||
if err == nil {
|
||||
return me
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
37
model/analytics_row_test.go
Обычный файл
37
model/analytics_row_test.go
Обычный файл
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAnalyticsRowJson(t *testing.T) {
|
||||
a1 := AnalyticsRow{}
|
||||
a1.Name = "2015-10-12"
|
||||
a1.Value = 12345.0
|
||||
json := a1.ToJson()
|
||||
ra1 := AnalyticsRowFromJson(strings.NewReader(json))
|
||||
|
||||
if a1.Name != ra1.Name {
|
||||
t.Fatal("days didn't match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnalyticsRowsJson(t *testing.T) {
|
||||
a1 := AnalyticsRow{}
|
||||
a1.Name = "2015-10-12"
|
||||
a1.Value = 12345.0
|
||||
|
||||
var a1s AnalyticsRows = make([]*AnalyticsRow, 1)
|
||||
a1s[0] = &a1
|
||||
|
||||
ljson := a1s.ToJson()
|
||||
results := AnalyticsRowsFromJson(strings.NewReader(ljson))
|
||||
|
||||
if a1s[0].Name != results[0].Name {
|
||||
t.Fatal("Ids do not match")
|
||||
}
|
||||
}
|
||||
@@ -416,6 +416,15 @@ func (c *Client) TestEmail(config *Config) (*Result, *AppError) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetAnalytics(teamId, name string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/admin/analytics/"+teamId+"/"+name, "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), AnalyticsRowsFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost("/channels/create", channel.ToJson()); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -23,6 +23,13 @@ type IncomingWebhook struct {
|
||||
TeamId string `json:"team_id"`
|
||||
}
|
||||
|
||||
type IncomingWebhookRequest struct {
|
||||
Text string `json:"text"`
|
||||
Username string `json:"username"`
|
||||
IconURL string `json:"icon_url"`
|
||||
ChannelName string `json:"channel"`
|
||||
}
|
||||
|
||||
func (o *IncomingWebhook) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
@@ -104,3 +111,14 @@ func (o *IncomingWebhook) PreSave() {
|
||||
func (o *IncomingWebhook) PreUpdate() {
|
||||
o.UpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o IncomingWebhookRequest
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,15 @@ func (o *PostList) AddPost(post *Post) {
|
||||
o.Posts[post.Id] = post
|
||||
}
|
||||
|
||||
func (o *PostList) Extend(other *PostList) {
|
||||
for _, postId := range other.Order {
|
||||
if _, ok := o.Posts[postId]; !ok {
|
||||
o.AddPost(other.Posts[postId])
|
||||
o.AddOrder(postId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PostList) Etag() string {
|
||||
|
||||
id := "0"
|
||||
|
||||
@@ -34,3 +34,37 @@ func TestPostListJson(t *testing.T) {
|
||||
t.Fatal("failed to serialize")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostListExtend(t *testing.T) {
|
||||
l1 := PostList{}
|
||||
|
||||
p1 := &Post{Id: NewId(), Message: NewId()}
|
||||
l1.AddPost(p1)
|
||||
l1.AddOrder(p1.Id)
|
||||
|
||||
p2 := &Post{Id: NewId(), Message: NewId()}
|
||||
l1.AddPost(p2)
|
||||
l1.AddOrder(p2.Id)
|
||||
|
||||
l2 := PostList{}
|
||||
|
||||
p3 := &Post{Id: NewId(), Message: NewId()}
|
||||
l2.AddPost(p3)
|
||||
l2.AddOrder(p3.Id)
|
||||
|
||||
l2.Extend(&l1)
|
||||
|
||||
if len(l1.Posts) != 2 || len(l1.Order) != 2 {
|
||||
t.Fatal("extending l2 changed l1")
|
||||
} else if len(l2.Posts) != 3 {
|
||||
t.Fatal("failed to extend posts l2")
|
||||
} else if l2.Order[0] != p3.Id || l2.Order[1] != p1.Id || l2.Order[2] != p2.Id {
|
||||
t.Fatal("failed to extend order of l2")
|
||||
}
|
||||
|
||||
if len(l1.Posts) != 2 || len(l1.Order) != 2 {
|
||||
t.Fatal("extending l2 again changed l1")
|
||||
} else if len(l2.Posts) != 3 || len(l2.Order) != 3 {
|
||||
t.Fatal("extending l2 again changed l2")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
)
|
||||
|
||||
type SearchParams struct {
|
||||
Terms string
|
||||
IsHashtag bool
|
||||
InChannel string
|
||||
FromUser string
|
||||
Terms string
|
||||
IsHashtag bool
|
||||
InChannels []string
|
||||
FromUsers []string
|
||||
}
|
||||
|
||||
var searchFlags = [...]string{"from", "channel", "in"}
|
||||
@@ -31,9 +31,9 @@ func splitWords(text string) []string {
|
||||
return words
|
||||
}
|
||||
|
||||
func parseSearchFlags(input []string) ([]string, map[string]string) {
|
||||
func parseSearchFlags(input []string) ([]string, [][2]string) {
|
||||
words := []string{}
|
||||
flags := make(map[string]string)
|
||||
flags := [][2]string{}
|
||||
|
||||
skipNextWord := false
|
||||
for i, word := range input {
|
||||
@@ -52,10 +52,10 @@ func parseSearchFlags(input []string) ([]string, map[string]string) {
|
||||
// check for case insensitive equality
|
||||
if strings.EqualFold(flag, searchFlag) {
|
||||
if value != "" {
|
||||
flags[searchFlag] = value
|
||||
flags = append(flags, [2]string{searchFlag, value})
|
||||
isFlag = true
|
||||
} else if i < len(input)-1 {
|
||||
flags[searchFlag] = input[i+1]
|
||||
flags = append(flags, [2]string{searchFlag, input[i+1]})
|
||||
skipNextWord = true
|
||||
isFlag = true
|
||||
}
|
||||
@@ -75,56 +75,66 @@ func parseSearchFlags(input []string) ([]string, map[string]string) {
|
||||
return words, flags
|
||||
}
|
||||
|
||||
func ParseSearchParams(text string) (*SearchParams, *SearchParams) {
|
||||
func ParseSearchParams(text string) []*SearchParams {
|
||||
words, flags := parseSearchFlags(splitWords(text))
|
||||
|
||||
hashtagTerms := []string{}
|
||||
plainTerms := []string{}
|
||||
hashtagTermList := []string{}
|
||||
plainTermList := []string{}
|
||||
|
||||
for _, word := range words {
|
||||
if validHashtag.MatchString(word) {
|
||||
hashtagTerms = append(hashtagTerms, word)
|
||||
hashtagTermList = append(hashtagTermList, word)
|
||||
} else {
|
||||
plainTerms = append(plainTerms, word)
|
||||
plainTermList = append(plainTermList, word)
|
||||
}
|
||||
}
|
||||
|
||||
inChannel := flags["channel"]
|
||||
if inChannel == "" {
|
||||
inChannel = flags["in"]
|
||||
hashtagTerms := strings.Join(hashtagTermList, " ")
|
||||
plainTerms := strings.Join(plainTermList, " ")
|
||||
|
||||
inChannels := []string{}
|
||||
fromUsers := []string{}
|
||||
|
||||
for _, flagPair := range flags {
|
||||
flag := flagPair[0]
|
||||
value := flagPair[1]
|
||||
|
||||
if flag == "in" || flag == "channel" {
|
||||
inChannels = append(inChannels, value)
|
||||
} else if flag == "from" {
|
||||
fromUsers = append(fromUsers, value)
|
||||
}
|
||||
}
|
||||
|
||||
fromUser := flags["from"]
|
||||
paramsList := []*SearchParams{}
|
||||
|
||||
var plainParams *SearchParams
|
||||
if len(plainTerms) > 0 {
|
||||
plainParams = &SearchParams{
|
||||
Terms: strings.Join(plainTerms, " "),
|
||||
IsHashtag: false,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
paramsList = append(paramsList, &SearchParams{
|
||||
Terms: plainTerms,
|
||||
IsHashtag: false,
|
||||
InChannels: inChannels,
|
||||
FromUsers: fromUsers,
|
||||
})
|
||||
}
|
||||
|
||||
var hashtagParams *SearchParams
|
||||
if len(hashtagTerms) > 0 {
|
||||
hashtagParams = &SearchParams{
|
||||
Terms: strings.Join(hashtagTerms, " "),
|
||||
IsHashtag: true,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
paramsList = append(paramsList, &SearchParams{
|
||||
Terms: hashtagTerms,
|
||||
IsHashtag: true,
|
||||
InChannels: inChannels,
|
||||
FromUsers: fromUsers,
|
||||
})
|
||||
}
|
||||
|
||||
// special case for when no terms are specified but we still have a filter
|
||||
if plainParams == nil && hashtagParams == nil && (inChannel != "" || fromUser != "") {
|
||||
plainParams = &SearchParams{
|
||||
Terms: "",
|
||||
IsHashtag: false,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
if len(plainTerms) == 0 && len(hashtagTerms) == 0 {
|
||||
paramsList = append(paramsList, &SearchParams{
|
||||
Terms: "",
|
||||
IsHashtag: true,
|
||||
InChannels: inChannels,
|
||||
FromUsers: fromUsers,
|
||||
})
|
||||
}
|
||||
|
||||
return plainParams, hashtagParams
|
||||
return paramsList
|
||||
}
|
||||
|
||||
@@ -28,25 +28,25 @@ func TestParseSearchFlags(t *testing.T) {
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana from:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["from"] != "chan" {
|
||||
} else if len(flags) != 1 || flags[0][0] != "from" || flags[0][1] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana from: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["from"] != "chan" {
|
||||
} else if len(flags) != 1 || flags[0][0] != "from" || flags[0][1] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana in: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["in"] != "chan" {
|
||||
} else if len(flags) != 1 || flags[0][0] != "in" || flags[0][1] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana channel:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["channel"] != "chan" {
|
||||
} else if len(flags) != 1 || flags[0][0] != "channel" || flags[0][1] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,14 @@ func TestParseSearchFlags(t *testing.T) {
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("channel: first in: second from:")); len(words) != 1 || words[0] != "from:" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 2 || flags["channel"] != "first" || flags["in"] != "second" {
|
||||
} else if len(flags) != 2 || flags[0][0] != "channel" || flags[0][1] != "first" || flags[1][0] != "in" || flags[1][1] != "second" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("channel: first channel: second from: third from: fourth")); len(words) != 0 {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 4 || flags[0][0] != "channel" || flags[0][1] != "first" || flags[1][0] != "channel" || flags[1][1] != "second" ||
|
||||
flags[2][0] != "from" || flags[2][1] != "third" || flags[3][0] != "from" || flags[3][1] != "fourth" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user