focalboard/mattermost-plugin/server/configuration.go
Scott Bishel 797d6bc04a
Implementation of Calendar MVP (#1741)
* initial commit

* turn on featureflag

* additional fixes

* update for using FullCalendar

* update to allow both calendars

* fix dnd, remove log messages

* fix lint, unit tests

* dates should use themselves for timezone offset

* fix for tests

* remove react-big-calendar

* remove react-big-calendar

* fix for handling feature flags changing

* clean up

* remove unit test

* update tests

* fix tests

* lint fixes

* add creating event, fixes

* linter fixes

* clean up

* add unit tests

* fixes

* update snapshots

* update test

* update snapshot

* disable test for now, timezone changes labels

* remove test to get to build

* remove snapshot

* feedback updates

* use getConfig instead

* linter fix

* more linter

* revert changes

* some fixes for issues

* fix for displaying new calendar

* fix for displaying new calendar

* add properties to cards

* add properties to cards

* read only implementation

* i18-extract

* implement unit tests

* implement unit tests

* fix test

* remove log statements

* remove feature flag from config

* updated icons

* Updating icons for calendar mvp

* Revert "Updating icons for calendar mvp"

This reverts commit e16e715e8a.

* Revert "updated icons"

This reverts commit 120b7b0b96.

* update for code reviews

* fix linter

* more feedback updates

* fix some styling

* fix lint errors

* Updating css

* Updating calendar css

* update for lint errors

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Asaad Mahmood <asaadmahmood@users.noreply.github.com>
2021-11-24 14:00:20 -07:00

94 lines
3.4 KiB
Go

package main
import (
"reflect"
)
// configuration captures the plugin's external configuration as exposed in the Mattermost server
// configuration, as well as values computed from the configuration. Any public fields will be
// deserialized from the Mattermost server configuration in OnConfigurationChange.
//
// As plugins are inherently concurrent (hooks being called asynchronously), and the plugin
// configuration can change at any time, access to the configuration must be synchronized. The
// strategy used in this plugin is to guard a pointer to the configuration, and clone the entire
// struct whenever it changes. You may replace this with whatever strategy you choose.
//
// If you add non-reference types to your configuration struct, be sure to rewrite Clone as a deep
// copy appropriate for your types.
type configuration struct {
EnablePublicSharedBoards bool
}
// Clone shallow copies the configuration. Your implementation may require a deep copy if
// your configuration has reference types.
func (c *configuration) Clone() *configuration {
var clone = *c
return &clone
}
// getConfiguration retrieves the active configuration under lock, making it safe to use
// concurrently. The active configuration may change underneath the client of this method, but
// the struct returned by this API call is considered immutable.
func (p *Plugin) getConfiguration() *configuration {
p.configurationLock.RLock()
defer p.configurationLock.RUnlock()
if p.configuration == nil {
return &configuration{}
}
return p.configuration
}
// setConfiguration replaces the active configuration under lock.
//
// Do not call setConfiguration while holding the configurationLock, as sync.Mutex is not
// reentrant. In particular, avoid using the plugin API entirely, as this may in turn trigger a
// hook back into the plugin. If that hook attempts to acquire this lock, a deadlock may occur.
//
// This method panics if setConfiguration is called with the existing configuration. This almost
// certainly means that the configuration was modified without being cloned and may result in
// an unsafe access.
func (p *Plugin) setConfiguration(configuration *configuration) {
p.configurationLock.Lock()
defer p.configurationLock.Unlock()
if configuration != nil && p.configuration == configuration {
// Ignore assignment if the configuration struct is empty. Go will optimize the
// allocation for same to point at the same memory address, breaking the check
// above.
if reflect.ValueOf(*configuration).NumField() == 0 {
return
}
panic("setConfiguration called with the existing configuration")
}
p.configuration = configuration
}
// OnConfigurationChange is invoked when configuration changes may have been made.
func (p *Plugin) OnConfigurationChange() error { //nolint
// Have we been setup by OnActivate?
if p.wsPluginAdapter == nil {
return nil
}
mmconfig := p.API.GetConfig()
// handle plugin configuration settings
enableShareBoards := false
if mmconfig.PluginSettings.Plugins[pluginName][sharedBoardsName] == true {
enableShareBoards = true
}
configuration := &configuration{
EnablePublicSharedBoards: enableShareBoards,
}
p.setConfiguration(configuration)
p.server.Config().EnablePublicSharedBoards = enableShareBoards
// handle feature flags
p.server.Config().FeatureFlags = parseFeatureFlags(mmconfig.FeatureFlags.ToMap())
p.server.UpdateAppConfig()
p.wsPluginAdapter.BroadcastConfigChange(*p.server.App().GetClientConfig())
return nil
}