Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanjay authored and sanjaydemansol committed Aug 27, 2021
1 parent 3395a30 commit 3ac3da8
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 20 deletions.
102 changes: 91 additions & 11 deletions server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -49,6 +50,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

Expand All @@ -69,7 +73,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")
}
Expand Down Expand Up @@ -147,25 +151,21 @@ func (p *Plugin) executeCommandQueue(args *model.CommandArgs) *model.CommandResp
message = strings.Join(split[3:], " ")
}

hashtag, error := p.GenerateHashtag(args.ChannelId, nextWeek, weekday)
hashtag, error := p.GenerateHashtag(args.ChannelId, nextWeek, weekday, false, time.Now().Weekday())
if error != nil {
return responsef("Error calculating hashtags. Check the meeting settings for this channel.")
}

searchResults, appErr := p.API.SearchPostsInTeamForUser(args.TeamId, args.UserId, model.SearchParameter{Terms: &hashtag})

if appErr != nil {
return responsef("Error calculating list number")
itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag)
if itemErr != nil {
return itemErr
}

postList := *searchResults.PostList
numQueueItems := len(postList.Posts)

_, appErr = p.API.CreatePost(&model.Post{
_, appErr := p.API.CreatePost(&model.Post{
UserId: args.UserId,
ChannelId: args.ChannelId,
RootId: args.RootId,
Message: fmt.Sprintf("#### %v %v) %v", hashtag, numQueueItems+1, message),
Message: fmt.Sprintf("#### %v %v) %v", hashtag, numQueueItems, message),
})
if appErr != nil {
return responsef("Error creating post: %s", appErr.Message)
Expand All @@ -174,6 +174,86 @@ 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("Can't find the meeting")
}

oldPostID := split[2]
postToBeReQueued, _ := p.API.GetPost(oldPostID)
var (
prefix string
hashtagDateFormat string
)
if matchGroups := meetingDateFormatRegex.FindStringSubmatch(meeting.HashtagFormat); len(matchGroups) == 4 {
prefix = matchGroups[1]
hashtagDateFormat = strings.TrimSpace(matchGroups[2])
} else {
return responsef("Error 203")
}

var (
messageRegexFormat = regexp.MustCompile(fmt.Sprintf(`(?m)^#### #%s(?P<date>.*) [0-9]+\) (?P<message>.*)?$`, prefix))
)

if matchGroups := messageRegexFormat.FindStringSubmatch(postToBeReQueued.Message); len(matchGroups) == 3 {
originalPostDate := strings.ReplaceAll(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")
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("We don't support re-queuing future items, only available for present and past items.")
}

hashtag, error := p.GenerateHashtag(args.ChannelId, false, -1, true, formattedDate.Weekday())
if error != nil {
return responsef("Error calculating hashtags. Check the meeting settings for this channel.")
}

itemErr, numQueueItems := calculateQueItemNumber(args, p, hashtag)
if itemErr != nil {
return itemErr
}

_, 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 {
return responsef("Error creating post: %s", appErr.Message)
}
return &model.CommandResponse{Text: fmt.Sprintf("Item has been Re-queued to %v", hashtag), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
}
return responsef("Make sure, message is in required format!")
}

func (p *Plugin) executeCommandHelp(args *model.CommandArgs) *model.CommandResponse {
return responsef(helpCommandText)
}
Expand Down
17 changes: 13 additions & 4 deletions server/meeting.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (p *Plugin) SaveMeeting(meeting *Meeting) error {
}

// GenerateHashtag returns a meeting hashtag
func (p *Plugin) GenerateHashtag(channelID string, nextWeek bool, weekday int) (string, error) {
func (p *Plugin) GenerateHashtag(channelID string, nextWeek bool, weekday int, requeue bool, assignedDay time.Weekday) (string, error) {
meeting, err := p.GetMeeting(channelID)
if err != nil {
return "", err
Expand All @@ -76,9 +76,18 @@ func (p *Plugin) GenerateHashtag(channelID string, nextWeek bool, weekday int) (
return "", err
}
} else {
// Get date for the list of days of the week
if meetingDate, err = nextWeekdayDateInWeek(meeting.Schedule, nextWeek); err != nil {
return "", err
// user didn't provide any specific date, Get date for the list of days of the week
if !requeue {
if meetingDate, err = nextWeekdayDateInWeek(meeting.Schedule, nextWeek); err != nil {
return "", err
}
} else {
if len(meeting.Schedule) == 1 && meeting.Schedule[0] == assignedDay { // if this day is the only day selected in settings
nextWeek = true
}
if meetingDate, err = nextWeekdayDateInWeekSkippingDay(meeting.Schedule, nextWeek, assignedDay); err != nil {
return "", err
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion server/meeting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestPlugin_GenerateHashtag(t *testing.T) {
jsonMeeting, err := json.Marshal(tt.args.meeting)
tAssert.Nil(err)
api.On("KVGet", tt.args.meeting.ChannelID).Return(jsonMeeting, nil)
got, err := mPlugin.GenerateHashtag(tt.args.meeting.ChannelID, tt.args.nextWeek, -1)
got, err := mPlugin.GenerateHashtag(tt.args.meeting.ChannelID, tt.args.nextWeek, -1, false, time.Now().Weekday()) // last parameter doesn't matter unless requeue
if (err != nil) != tt.wantErr {
t.Errorf("GenerateHashtag() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
19 changes: 19 additions & 0 deletions server/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

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.
Expand Down
35 changes: 32 additions & 3 deletions webapp/src/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {searchPostsWithParams} from 'mattermost-redux/actions/search';

import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {Client4} from 'mattermost-redux/client';

import Client from '../client';

import ActionTypes from '../action_types';

export function fetchMeetingSettings(channelId = '') {
Expand Down Expand Up @@ -80,4 +80,33 @@ export function performSearch(terms) {

return dispatch(searchPostsWithParams(teamId, {terms, is_or_search: false, include_deleted_channels: viewArchivedChannels, page: 0, per_page: 20}, true));
};
}
}

export function requeueItem(itemId) {
return async (dispatch, getState) => {
const command = `/agenda requeue ${itemId}`;
await clientExecuteCommand(dispatch, getState, command);
return {data: true};
};
}

export async function clientExecuteCommand(dispatch, getState, command) {
let currentChannel = getCurrentChannel(getState());
const currentTeamId = getCurrentTeamId(getState());

// Default to town square if there is no current channel (i.e., if Mattermost has not yet loaded)
if (!currentChannel) {
currentChannel = await Client4.getChannelByName(currentTeamId, 'town-square');
}

const args = {
channel_id: currentChannel?.id,
team_id: currentTeamId,
};

try {
return Client4.executeCommand(command, args);
} catch (error) {
return error;
}
}
6 changes: 5 additions & 1 deletion webapp/src/index.js
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';

Expand All @@ -19,6 +19,10 @@ export default class Plugin {
(channelId) => {
store.dispatch(openMeetingSettingsModal(channelId));
});

registry.registerPostDropdownMenuAction('Re-queue', (params) => {
store.dispatch(requeueItem(params));
});
}
}

Expand Down

0 comments on commit 3ac3da8

Please sign in to comment.