-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GH-12] Added Ability to re-queue agenda Items. #89
Changes from all commits
19f30a6
51a8315
e4aa842
907377f
9457541
f4c0c33
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -57,6 +57,9 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo | |||||||
case "queue": | ||||||||
return p.executeCommandQueue(args), nil | ||||||||
|
||||||||
case "requeue": | ||||||||
return p.executeCommandReQueue(args), nil | ||||||||
|
||||||||
case "setting": | ||||||||
return p.executeCommandSetting(args), nil | ||||||||
|
||||||||
|
@@ -77,7 +80,7 @@ func (p *Plugin) executeCommandList(args *model.CommandArgs) *model.CommandRespo | |||||||
weekday = int(parsedWeekday) | ||||||||
} | ||||||||
|
||||||||
hashtag, err := p.GenerateHashtag(args.ChannelId, nextWeek, weekday) | ||||||||
hashtag, err := p.GenerateHashtag(args.ChannelId, nextWeek, weekday, false, time.Now().Weekday()) | ||||||||
if err != nil { | ||||||||
return responsef("Error calculating hashtags") | ||||||||
} | ||||||||
|
@@ -160,7 +163,7 @@ func (p *Plugin) executeCommandQueue(args *model.CommandArgs) *model.CommandResp | |||||||
message = strings.Join(split[3:], " ") | ||||||||
} | ||||||||
|
||||||||
hashtag, err := p.GenerateHashtag(args.ChannelId, nextWeek, weekday) | ||||||||
hashtag, err := p.GenerateHashtag(args.ChannelId, nextWeek, weekday, false, time.Now().Weekday()) | ||||||||
if err != nil { | ||||||||
return responsef("Error calculating hashtags. Check the meeting settings for this channel.") | ||||||||
} | ||||||||
|
@@ -183,6 +186,99 @@ func (p *Plugin) executeCommandQueue(args *model.CommandArgs) *model.CommandResp | |||||||
return &model.CommandResponse{} | ||||||||
} | ||||||||
|
||||||||
func calculateQueItemNumber(args *model.CommandArgs, p *Plugin, hashtag string) (*model.CommandResponse, int) { | ||||||||
searchResults, appErr := p.API.SearchPostsInTeamForUser(args.TeamId, args.UserId, model.SearchParameter{Terms: &hashtag}) | ||||||||
if appErr != nil { | ||||||||
return responsef("Error calculating list number"), 0 | ||||||||
} | ||||||||
postList := *searchResults.PostList | ||||||||
numQueueItems := len(postList.Posts) | ||||||||
return nil, numQueueItems + 1 | ||||||||
} | ||||||||
|
||||||||
func (p *Plugin) executeCommandReQueue(args *model.CommandArgs) *model.CommandResponse { | ||||||||
split := strings.Fields(args.Command) | ||||||||
|
||||||||
if len(split) <= 2 { | ||||||||
return responsef("Missing parameters for requeue command") | ||||||||
} | ||||||||
|
||||||||
meeting, err := p.GetMeeting(args.ChannelId) | ||||||||
if err != nil { | ||||||||
return responsef("There was no meeting found for this channel.") | ||||||||
} | ||||||||
|
||||||||
oldPostID := split[2] | ||||||||
postToBeReQueued, appErr := p.API.GetPost(oldPostID) | ||||||||
if appErr != nil { | ||||||||
p.API.LogWarn("Error fetching post: %s", "error", appErr.Message) | ||||||||
return responsef("Error fetching post.") | ||||||||
} | ||||||||
var ( | ||||||||
prefix string | ||||||||
hashtagDateFormat string | ||||||||
) | ||||||||
matchGroups := meetingDateFormatRegex.FindStringSubmatch(meeting.HashtagFormat) | ||||||||
if len(matchGroups) != 3 { | ||||||||
responsef("Error parsing hashtag format.") | ||||||||
} | ||||||||
prefix = matchGroups[1] | ||||||||
hashtagDateFormat = strings.TrimSpace(matchGroups[2]) | ||||||||
|
||||||||
var ( | ||||||||
messageRegexFormat, er = regexp.Compile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix)) | ||||||||
) | ||||||||
if er != nil { | ||||||||
return responsef(er.Error()) | ||||||||
} | ||||||||
|
||||||||
if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to avoid this large indented block here
Suggested change
Then return an error in that if block, and continue on otherwise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great, done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems that this is not done |
||||||||
originalPostDate := p.replaceUnderscoreWithSpace(strings.TrimSpace(matchGroups[1])) // reverse what we do to make it a valid hashtag | ||||||||
originalPostMessage := strings.TrimSpace(matchGroups[2]) | ||||||||
|
||||||||
today := time.Now() | ||||||||
local, _ := time.LoadLocation("Local") | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, should I remove it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is usually used instead, or is the only instance of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sanjaydemansol Please see my question above:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No localized methods are used anywhere. removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. time.LoadLocation is stored in local and is used here at. |
||||||||
formattedDate, _ := time.ParseInLocation(hashtagDateFormat, originalPostDate, local) | ||||||||
if formattedDate.Year() == 0 { | ||||||||
thisYear := today.Year() | ||||||||
formattedDate = formattedDate.AddDate(thisYear, 0, 0) | ||||||||
} | ||||||||
|
||||||||
if today.Year() <= formattedDate.Year() && today.YearDay() < formattedDate.YearDay() { | ||||||||
return responsef("Re-queuing future items is not supported.") | ||||||||
} | ||||||||
|
||||||||
hashtag, err := p.GenerateHashtag(args.ChannelId, false, -1, true, formattedDate.Weekday()) | ||||||||
if err != nil { | ||||||||
p.API.LogWarn("Error calculating hashtags. Check the meeting settings for this channel.", "error", err.Error()) | ||||||||
return responsef("Error calculating hashtags. Check the meeting settings for this channel.") | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error should be logged There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||||||
} | ||||||||
|
||||||||
commandResponse, numQueueItems := calculateQueItemNumber(args, p, hashtag) | ||||||||
if commandResponse != nil { | ||||||||
return commandResponse | ||||||||
} | ||||||||
|
||||||||
_, appErr := p.API.UpdatePost(&model.Post{ | ||||||||
Id: oldPostID, | ||||||||
UserId: args.UserId, | ||||||||
ChannelId: args.ChannelId, | ||||||||
RootId: args.RootId, | ||||||||
Message: fmt.Sprintf("#### %v %v) %v", hashtag, numQueueItems, originalPostMessage), | ||||||||
}) | ||||||||
if appErr != nil { | ||||||||
p.API.LogWarn("Error creating post: %s", "error", appErr.Message) | ||||||||
return responsef("Error creating post: %s", appErr.Message) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error should be logged There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||||||
} | ||||||||
return responsef(fmt.Sprintf("Item has been Re-queued to %v", hashtag)) | ||||||||
} | ||||||||
return responsef("Make sure, message is in required format.") | ||||||||
} | ||||||||
|
||||||||
func (p *Plugin) replaceUnderscoreWithSpace(hashtag string) string { | ||||||||
return strings.ReplaceAll(hashtag, "_", " ") | ||||||||
} | ||||||||
|
||||||||
func parseMeetingPost(meeting *Meeting, post *model.Post) (string, ParsedMeetingMessage, error) { | ||||||||
var ( | ||||||||
prefix string | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,25 @@ func nextWeekdayDateInWeek(meetingDays []time.Weekday, nextWeek bool) (*time.Tim | |
return nextWeekdayDate(meetingDay, nextWeek) | ||
} | ||
|
||
func nextWeekdayDateInWeekSkippingDay(meetingDays []time.Weekday, nextWeek bool, dayToSkip time.Weekday) (*time.Time, error) { | ||
if len(meetingDays) == 0 { | ||
return nil, errors.New("missing weekdays to calculate date") | ||
} | ||
|
||
todayWeekday := time.Now().Weekday() | ||
|
||
// Find which meeting weekday to calculate the date for | ||
meetingDay := meetingDays[0] | ||
for _, day := range meetingDays { | ||
if todayWeekday <= day && day != dayToSkip { | ||
meetingDay = day | ||
break | ||
} | ||
} | ||
Comment on lines
+83
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we write unit tests for this function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
|
||
return nextWeekdayDate(meetingDay, nextWeek) | ||
} | ||
|
||
// nextWeekdayDate calculates the date of the next given weekday | ||
// from today's date. | ||
// If nextWeek is true, it will be based on the next calendar week. | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,8 +1,11 @@ | ||||||
package main | ||||||
|
||||||
import ( | ||||||
"reflect" | ||||||
"testing" | ||||||
"time" | ||||||
|
||||||
"github.com/undefinedlabs/go-mpatch" | ||||||
) | ||||||
|
||||||
func Test_parseSchedule(t *testing.T) { | ||||||
|
@@ -41,3 +44,42 @@ func Test_parseSchedule(t *testing.T) { | |||||
}) | ||||||
} | ||||||
} | ||||||
|
||||||
func Test_nextWeekdayDateInWeekSkippingDay(t *testing.T) { | ||||||
var patch, err = mpatch.PatchMethod(time.Now, func() time.Time { | ||||||
return time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC) | ||||||
}) | ||||||
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking we would pass in the value for We would modify now, _ := time.Date(2021, 11, 15, 00, 00, 00, 0, time.UTC)
got, err := nextWeekdayDateInWeekSkippingDay(now, tt.args.meetingDays, tt.args.nextWeek, tt.args.dayToSkip) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use |
||||||
if patch == nil || err != nil { | ||||||
t.Errorf("error creating patch") | ||||||
} | ||||||
type args struct { | ||||||
meetingDays []time.Weekday | ||||||
nextWeek bool | ||||||
dayToSkip time.Weekday | ||||||
} | ||||||
tests := []struct { | ||||||
name string | ||||||
args args | ||||||
want time.Time | ||||||
wantErr bool | ||||||
}{ | ||||||
|
||||||
{name: "test skip tuesday in week, today", args: args{[]time.Weekday{1, 2, 3, 4, 5, 6, 7}, false, time.Weekday(2)}, want: time.Now().AddDate(0, 0, 0), wantErr: false}, | ||||||
{name: "test skip tuesday in few days", args: args{[]time.Weekday{2, 3, 4, 5, 6, 7}, false, time.Weekday(2)}, want: time.Now().AddDate(0, 0, 2), wantErr: false}, | ||||||
{name: "test skip monday with nextWeek true", args: args{[]time.Weekday{1, 2, 3, 4}, true, time.Weekday(1)}, want: time.Now().AddDate(0, 0, 8), wantErr: false}, | ||||||
{name: "test only meeting day is skipped", args: args{[]time.Weekday{3}, false, time.Weekday(3)}, want: time.Now().AddDate(0, 0, 2), wantErr: false}, | ||||||
{name: "test only meeting day is skipped with nextWeek true", args: args{[]time.Weekday{3}, true, time.Weekday(3)}, want: time.Now().AddDate(0, 0, 9), wantErr: false}, | ||||||
} | ||||||
for _, tt := range tests { | ||||||
t.Run(tt.name, func(t *testing.T) { | ||||||
got, err := nextWeekdayDateInWeekSkippingDay(tt.args.meetingDays, tt.args.nextWeek, tt.args.dayToSkip) | ||||||
if (err != nil) != tt.wantErr { | ||||||
t.Errorf("nextWeekdayDateInWeekSkippingDay() error = %v, wantErr %v", err, tt.wantErr) | ||||||
return | ||||||
} | ||||||
if !reflect.DeepEqual(got, &tt.want) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this also work?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mickmister tested code added |
||||||
t.Errorf("nextWeekdayDateInWeekSkippingDay() got = %v, want %v", got, tt.want) | ||||||
} | ||||||
}) | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
|
||
import {updateSearchTerms, updateSearchResultsTerms, updateRhsState, performSearch, openMeetingSettingsModal} from './actions'; | ||
import {updateSearchTerms, updateSearchResultsTerms, updateRhsState, performSearch, openMeetingSettingsModal, requeueItem} from './actions'; | ||
|
||
import reducer from './reducer'; | ||
|
||
|
@@ -19,6 +19,10 @@ export default class Plugin { | |
(channelId) => { | ||
store.dispatch(openMeetingSettingsModal(channelId)); | ||
}); | ||
|
||
registry.registerPostDropdownMenuAction('Re-queue', (postId) => { | ||
store.dispatch(requeueItem(postId)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to use
|
||
}); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot going on in this function. Can we pull some of the logic out to be unit tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah absolutely, will refactor it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like this function was refactored, but we agreed it should be refactored and tested in this conversation