Skip to content
This repository was archived by the owner on Dec 6, 2023. It is now read-only.

WIP Issue 73 #137

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8e8ebc5
demo webapp copied
scottleedavis May 2, 2019
04dd622
demo webapp copied
scottleedavis May 2, 2019
5ae02a6
Merge branch 'issue_73' of github.com:scottleedavis/mattermost-plugin…
scottleedavis May 4, 2019
616cd4c
demo webapp copied
scottleedavis May 2, 2019
dc775c1
Merge branch 'issue_73' of github.com:scottleedavis/mattermost-plugin…
scottleedavis May 5, 2019
e31515d
wip
scottleedavis May 5, 2019
cdc78f7
wip
scottleedavis May 7, 2019
37b9ade
cleaned up. postId in menu click
scottleedavis May 8, 2019
bafafa0
Merge branch 'master' into issue_73
scottleedavis May 8, 2019
9842cd5
api connected with menu click.
scottleedavis May 8, 2019
cf09b31
Merge branch 'master' into issue_73
scottleedavis May 11, 2019
6cf5c6b
Merge branch 'master' into issue_73
scottleedavis May 18, 2019
ef7c103
wip
scottleedavis May 18, 2019
e1137dc
drop down demo
scottleedavis May 18, 2019
9517aee
Merge branch 'master' into issue_73
scottleedavis May 22, 2019
c51521d
Merge branch 'master' into issue_73
scottleedavis Jun 1, 2019
35636a3
version bump
scottleedavis Jun 1, 2019
032ca49
prep for new submenu
scottleedavis Jul 30, 2019
20a914a
Merge branch 'master' into issue_73
scottleedavis Jul 30, 2019
893891c
mvp complete for post submenu to reminder
scottleedavis Jul 30, 2019
0a1c2cc
add node to build container
scottleedavis Jul 30, 2019
a7329c6
updated package.json dependencies and webpack config
scottleedavis Jul 31, 2019
c478d5a
Merge branch 'master' into issue_73
scottleedavis Aug 6, 2019
cf06e70
updated subMenu object structure
scottleedavis Aug 6, 2019
c8e9fbe
improved test coverage
scottleedavis Aug 7, 2019
cacb152
time format change in test
scottleedavis Aug 7, 2019
875b9f7
circle ci test
scottleedavis Aug 7, 2019
e819fb0
circle ci timezone accounting in test
scottleedavis Aug 7, 2019
b0b0708
removed errant format
scottleedavis Aug 7, 2019
3205da9
more circle ci test fixes
scottleedavis Aug 7, 2019
d0ff109
Merge branch 'master' into issue_73
scottleedavis Aug 10, 2019
829b203
cleanup post master merge
scottleedavis Aug 10, 2019
f627512
require siteURL for post links
scottleedavis Aug 10, 2019
6f0601d
remove all siteurl dependencies
scottleedavis Aug 10, 2019
834fe81
increased test coverage
scottleedavis Aug 10, 2019
825a774
Merge branch 'master' into issue_73
scottleedavis Aug 15, 2019
a31a11e
Merge branch 'master' into issue_73
scottleedavis Aug 20, 2019
e117b97
Merge branch 'master' into issue_73
scottleedavis Aug 26, 2019
20c0a94
Merge branch 'master' into issue_73
scottleedavis Aug 27, 2019
b634bc7
test cleanup
scottleedavis Aug 27, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ orbs:
jobs:
build:
docker:
- image: circleci/golang:1.12
- image: circleci/golang:1.12-node

working_directory: /go/src/github.com/scottleedavis/mattermost-plugin-remind
steps:
- checkout

# specify any bash command here prefixed with `run: `
- run: go get -v -t -d ./...
# - run: go test -v ./...
- run: make test
- codecov/upload:
file: server/coverage.txt
file: server/coverage.txt
28 changes: 28 additions & 0 deletions assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,18 @@
"id": "schedule.response",
"translation": "I will remind {{.Target}}{{.UseTo}} \"{{.Message}}\" {{.When}}"
},
{
"id": "schedule.post.response",
"translation": "I will remind you about [this message]({{.PostLink}}) (\"{{.Message}}\") {{.When}}"
},
{
"id": "reminder.message",
"translation": "{{.FinalTarget}} asked me to remind you \"{{.Message}}\"."
},
{
"id": "reminder.post.message",
"translation": "You asked me to remind you about [this message]({{.PostLink}})."
},
{
"id": "action.complete",
"translation": "I've marked \"{{.Message}}\" as complete."
Expand All @@ -111,6 +119,26 @@
"id": "action.delete",
"translation": "I’ve deleted the reminder \"{{.Message}}\"."
},
{
"id": "action.20min",
"translation": "in 20 minutes"
},
{
"id": "action.1hr",
"translation": "in 1 hour"
},
{
"id": "action.3hr",
"translation": "in 3 hours"
},
{
"id": "action.tomorrow",
"translation": "tomorrow"
},
{
"id": "action.nextweek",
"translation": "on monday"
},
{
"id": "action.snooze.20min",
"translation": "Snoozed. I’ll remind you \"{{.Message}}\" in 20 minutes"
Expand Down
3 changes: 3 additions & 0 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"windows-amd64": "server/dist/plugin-windows-amd64.exe"
}
},
"webapp": {
"bundle_path": "webapp/dist/main.js"
},
"settings_schema": {
"header": "",
"footer": "",
Expand Down
1 change: 0 additions & 1 deletion server/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const botName = "remindbot"
const botDisplayName = "Remindbot"

func (p *Plugin) OnActivate() error {
p.ServerConfig = p.API.GetConfig()

teams, err := p.API.GetTeams()
if err != nil {
Expand Down
151 changes: 151 additions & 0 deletions server/http.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"net/http"
Expand All @@ -11,8 +12,20 @@ import (
"github.com/mattermost/mattermost-server/plugin"
)

type ReminderHTTPRequest struct {
PostId string

UserId string

TeamId string

TimeId string
}

func (p *Plugin) InitAPI() *mux.Router {
r := mux.NewRouter()

r.HandleFunc("/remind/{id:[a-z0-9]+}", p.handleReminder).Methods("POST")
r.HandleFunc("/dialog", p.handleDialog).Methods("POST")

r.HandleFunc("/view/ephemeral", p.handleViewEphemeral).Methods("POST")
Expand Down Expand Up @@ -40,6 +53,144 @@ func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Req
p.router.ServeHTTP(w, r)
}

func (p *Plugin) handleReminder(w http.ResponseWriter, r *http.Request) {

decoder := json.NewDecoder(r.Body)
var request ReminderHTTPRequest
err := decoder.Decode(&request)
if err != nil {
panic(err)
}

user, uErr := p.API.GetUser(request.UserId)
if uErr != nil {
p.API.LogError(uErr.Error())
writePostActionIntegrationResponseError(w, &model.PostActionIntegrationResponse{})
return
}
post, pErr := p.API.GetPost(request.PostId)
if pErr != nil {
p.API.LogError(pErr.Error())
writePostActionIntegrationResponseError(w, &model.PostActionIntegrationResponse{})
return
}
team, tErr := p.API.GetTeam(request.TeamId)
if tErr != nil {
p.API.LogError(tErr.Error())
writePostActionIntegrationResponseError(w, &model.PostActionIntegrationResponse{})
}

location := p.location(user)
T, _ := p.translation(user)

var timeChoice string
switch request.TimeId {
case "20min":
timeChoice = T("action.20min")
case "1hr":
timeChoice = T("action.1hr")
case "3hr":
timeChoice = T("action.3hr")
case "tomorrow":
timeChoice = T("action.tomorrow")
case "nextweek":
timeChoice = T("action.nextweek")
default:
timeChoice = request.TimeId
}

rr := &ReminderRequest{
TeamId: team.Id,
Username: user.Username,
Reminder: Reminder{
Id: model.NewId(),
TeamId: team.Id,
PostId: post.Id,
Username: user.Username,
Message: post.Message,
Completed: p.emptyTime,
Target: "@" + user.Username,
When: timeChoice,
},
}

if cErr := p.CreateOccurrences(rr); cErr != nil {
p.API.LogError(cErr.Error())
writePostActionIntegrationResponseError(w, &model.PostActionIntegrationResponse{})
return
}

if rErr := p.UpsertReminder(rr); rErr != nil {
p.API.LogError(rErr.Error())
writePostActionIntegrationResponseError(w, &model.PostActionIntegrationResponse{})
return
}

t := ""
if len(rr.Reminder.Occurrences) > 0 {
t = rr.Reminder.Occurrences[0].Occurrence.In(location).Format(time.RFC3339)
}
message := post.Message
if len(message) > 9 {
message = message[0:9] + "..."
}

var responseParameters = map[string]interface{}{
"PostLink": "/" + team.Name + "/pl/" + post.Id,
"Message": message,
"When": p.formatWhen(
rr.Username,
rr.Reminder.When,
t,
false,
),
}

responsePost := &model.Post{
ChannelId: post.ChannelId,
UserId: p.remindUserId,
Props: model.StringInterface{
"attachments": []*model.SlackAttachment{
{
Text: T("schedule.post.response", responseParameters),
Actions: []*model.PostAction{
{
Id: model.NewId(),
Integration: &model.PostActionIntegration{
Context: model.StringInterface{
"reminder_id": rr.Reminder.Id,
"occurrence_id": rr.Reminder.Occurrences[0].Id,
"action": "delete/ephemeral",
},
URL: fmt.Sprintf("/plugins/%s/delete/ephemeral", manifest.Id),
},
Type: model.POST_ACTION_TYPE_BUTTON,
Name: T("button.delete"),
},
{
Id: model.NewId(),
Integration: &model.PostActionIntegration{
Context: model.StringInterface{
"reminder_id": rr.Reminder.Id,
"occurrence_id": rr.Reminder.Occurrences[0].Id,
"action": "view/ephemeral",
},
URL: fmt.Sprintf("/plugins/%s/view/ephemeral", manifest.Id),
},
Type: model.POST_ACTION_TYPE_BUTTON,
Name: T("button.view.reminders"),
},
},
},
},
},
}
p.API.SendEphemeralPost(user.Id, responsePost)

writePostActionIntegrationResponseOk(w, &model.PostActionIntegrationResponse{})

}

func (p *Plugin) handleDialog(w http.ResponseWriter, req *http.Request) {

request := model.SubmitDialogRequestFromJson(req.Body)
Expand Down
68 changes: 68 additions & 0 deletions server/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,74 @@ import (
"github.com/stretchr/testify/mock"
)

func TestHandleReminder(t *testing.T) {

user := &model.User{
Id: model.NewId(),
Username: model.NewRandomString(10),
}

post := &model.Post{
Id: model.NewId(),
}

team := &model.Team{
Id: model.NewId(),
}

reminderRequest := ReminderHTTPRequest{
PostId: post.Id,
UserId: user.Id,
TeamId: team.Id,
}

testTime := time.Now().UTC().Round(time.Second)
occurrences := []Occurrence{
{
Id: model.NewId(),
ReminderId: model.NewId(),
Occurrence: testTime,
},
}

stringOccurrences, _ := json.Marshal(occurrences)
setupAPI := func() *plugintest.API {
api := &plugintest.API{}
api.On("LogDebug", mock.Anything, mock.Anything, mock.Anything).Maybe()
api.On("LogError", mock.Anything, mock.Anything, mock.Anything).Maybe()
api.On("LogInfo", mock.Anything).Maybe()
api.On("GetUser", mock.Anything).Return(user, nil)
api.On("GetUserByUsername", mock.Anything).Return(user, nil)
api.On("GetPost", mock.Anything).Return(post, nil)
api.On("GetTeam", mock.Anything).Return(team, nil)
api.On("KVGet", mock.Anything).Return(stringOccurrences, nil)
api.On("KVSet", mock.Anything, mock.Anything).Return(nil)
api.On("SendEphemeralPost", mock.Anything, mock.Anything).Return(nil)

return api
}

t.Run("handle reminder created from webapp", func(t *testing.T) {

api := setupAPI()
defer api.AssertExpectations(t)

p := &Plugin{}
p.router = p.InitAPI()
p.API = api

reminderRequest.TimeId = "in 20 minutes"
reminderJson, _ := json.Marshal(&reminderRequest)
w := httptest.NewRecorder()
r := httptest.NewRequest("POST", "/remind/"+post.Id, bytes.NewReader(reminderJson))
p.ServeHTTP(nil, w, r)

result := w.Result()
assert.NotNil(t, result)

})
}

func TestHandleDialog(t *testing.T) {
user := &model.User{
Id: model.NewId(),
Expand Down
Loading