-
Notifications
You must be signed in to change notification settings - Fork 23
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
Add settings panel #62
Conversation
Hmmm. Is there a way to indicate via the interactive buttons what is currently set? (ie: an active border around "Yes") @asaadmahmood any ideas on how to best articulate to the user what is currently set already? I'm thinking of changing the verbiage on current status to:
@asaadmahmood Should we use "I" to refer to the CalendarBot itself?
|
If we were to wait for this PR we would be able to apply some color to the one selected. Not sure if it is the best way to show it. |
I didn't get this, what is "I"? For the second one, I'd suggest: I'm guessing the user only sees this one, not again and again, because if he has selected either yes or no, that's his setting, and he can change it when he wants, rather than seeing that message popup time and time again. So it makes sense not to focus on what the setting is right now i.e. Currently, and just ask him what he wants to do. |
@asaadmahmood with "I" Aaron refers to "I" as in "I, me, myself" or "I, you, he". The idea of this is to work as a "panel". It will be always present there until it is somehow closed (in the current implementation, it is only when we disconnect, or write /settings again). It would be a similar idea to go to the system settings, and change settings there. |
Got it. Yeah I think we can use "I" to get a more personal feel. |
You are right. The post will be seldom reused, and we will have to write |
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.
LGTM
"github.com/mattermost/mattermost-server/v5/model" | ||
) | ||
|
||
type sh struct { |
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.
1/5 s/sh/handler/
server/utils/bot/poster.go
Outdated
DeletePost(postID string) error | ||
|
||
// DMUpdatePost substitute one post with another | ||
DMUpdatePost(post *model.Post) error |
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.
s/DMUpdatePost/UpdatePost/ ??
Nice stuff! I think it'll need to mature and get simplified a bit, but I want to use it, now! |
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.
Great separation of concerns. I really like the generic implementation in the utils/settingspanel
package. LGTM 👍
GetConfirmationSettingID = "get_confirmation" | ||
) | ||
|
||
func (s *pluginStore) SetSetting(userID, settingID string, value interface{}) error { |
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.
value interface{}
Great, I see this can support strings as well 👍
Codecov Report
@@ Coverage Diff @@
## master #62 +/- ##
==========================================
- Coverage 26.20% 23.85% -2.36%
==========================================
Files 57 60 +3
Lines 2015 2218 +203
==========================================
+ Hits 528 529 +1
- Misses 1432 1634 +202
Partials 55 55
Continue to review full report at Codecov.
|
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.
Great job @larkox! I have a few questions and requests since last review
|
||
actions = []*model.PostAction{&actionOptionsH, &actionOptionsM, &actionOptionsAPM} | ||
|
||
if currentTextValue != "Not set" { |
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.
currentTextValue
is initialized as Not set.
but is being compared to Not set
here.
server/store/setting_store.go
Outdated
stringValue := value.(string) | ||
splittedValue := strings.Split(stringValue, " ") | ||
timezone := strings.Join(splittedValue[1:], " ") | ||
|
||
found := false | ||
for _, dsum := range dsumIndex { | ||
if dsum.MattermostUserID == userID { | ||
stringValue := value.(string) | ||
if stringValue == "true" { | ||
found = true | ||
|
||
if splittedValue[0] == "true" { | ||
dsum.Enable = true | ||
break | ||
} | ||
|
||
if stringValue == "false" { | ||
if splittedValue[0] == "false" { | ||
dsum.Enable = false | ||
break | ||
} | ||
|
||
dsum.PostTime = value.(string) | ||
dsum.PostTime = splittedValue[0] | ||
dsum.Timezone = timezone |
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.
This seems pretty hacky to me. What is the reason for needing to accept interface{}
here?
Maybe make a struct to pass in here instead of doing string parsing. We can still accept interface{}
, but assert it to be what we expect it to be. This way, the caller can be more specific with what it's passing.
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 are many considerations here to do it this way.
First of all, this function is called (with a few steps) by the handler, which is agnostic.
The handler passes the context in case of buttons, the option in case of selects. Since this is a select in general, we should receive a string, which is the only value an option can have, and then parse it.
Regarding receiving interface instead of string, is just to make the type conversions where it makes sense, which is here. Otherwise, we would have to make the conversions in the case block on the switch on SetSetting.
We could put all the parsing in one function that returns this struct you are talking about, but I am not sure whether it would improve the readibility.
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.
What happens when this value gets more complicated, or we have a more complicated value we have to handle similarly? Is there anyway the origin of the data can tell this function "this is the post time", or "this is the enable flag"? For example, if this store value had more than one boolean, this would not work.
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.
We could codify the option content as a JSON string. What do you think?
server/store/setting_store.go
Outdated
} | ||
} | ||
|
||
return "Daily summary not set", nil | ||
err = s.SaveDailySummaryIndex(dsumIndex) |
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.
StoreDailySummaryUserSettings
is available so you don't need to access the index directly
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.
Thanks for addressing the feedback @larkox! LGTM after a few more questions/comments are resolved
currentValueMessage := "Disabled" | ||
|
||
actions := []*model.PostAction{} | ||
if !disabled { |
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.
This !disabled
block is pretty long, leading up to just about the end of the function. Do you think we can instead have a short if disabled
block that returns early on?
if dsum != nil { | ||
timezone = dsum.Timezone | ||
} else { | ||
timezone = "UTC" |
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.
I'm not sure what benefit the user gets in setting their settings with the wrong timezone. 1/5 Instead of falling back on UTC, return an error here saying that we couldn't get their timezone from Microsoft.
|
||
actions = []*model.PostAction{&actionOptionsH, &actionOptionsM, &actionOptionsAPM} | ||
|
||
buttonText := "Enable" |
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.
What purpose did the if currentTextValue == "Not set."
block serve that is no longer necessary? Just want to understand the code.
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.
The idea was not to show the Enable button before a Daily Summary was set, but I thought that it would make sense to allow the enable with the default value.
…taken from Microsoft
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.
Awesome! LGTM 👍
LGTM |
/update-branch |
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.
Spoke with @mickmister We want to merge this now to be verified in master. This will aid in making other PRs more testable.
Summary
Created an implementation for the settings panel which use post messages with slack attachments. This setting panel should be reusable for other projects.
Ticket Link
Fixes #61